1. 设计模式之策略模式:替换掉屎一样的if else语句
1.1. 介绍
在策略模式(Strategy Pattern)中一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。通过使用策略模式,可以在运行时根据需要选择不同的算法,而不需要修改客户端代码。
要点1:必须将
if else
的代码,封装到不同的策略类中。要点2:将选择哪种策略的逻辑给放到一个工厂类中去,选择策略的代码务必很简洁。
要点3:context可有可无,具体是看你的策略执行这块如果就一行代码调用,不需要context。如果策略执行逻辑较复杂,可以用context来封装执行逻辑。
设计模式的重点是思想,大部分业务场景不会只有一种设计模式,很多情况都是多种设计模式相结合。例如策略模式,往往需要结合工厂模式来使用。。
应用实例
支付方式选择: 支付宝、微信支付、银行卡等策略动态切换。
游戏角色技能: 不同武器对应不同的攻击策略。
数据压缩/加密: 支持多种压缩算法(ZIP、RAR)或加密方式(AES、DES)。
优惠券计价: 计算价格时,不同优惠券计价逻辑不同。
优缺点及建议
优点
1.避免多重条件语句,代码更清晰。
2.易于扩展新算法(开闭原则)。
3.算法可复用和单元测试。
缺点
1.客户端需了解所有策略类(需权衡)。可以配合工厂模式来避免。
2.策略类数量可能增多(需合理设计)。
使用建议
1.当系统中有多种算法或行为,且它们之间可以相互替换时,使用策略模式。
2.当系统需要动态选择算法时,策略模式是一个合适的选择。
注意事项
1.如果系统中策略类数量过多,考虑使用其他模式或设计技巧来解决类膨胀问题。
1.2. 实现及相关代码
假设某业务需要优惠券计价,根据类型不同,选择不同优惠券进行计价。
1.2.1. 没使用设计模式方式
调用方法
public static void main(String[] args) {
// 优惠券类型
int discountStyle = 1;
if(discountStyle == 1) {
System.out.println("执行优惠计价方式1的复杂业务逻辑");
} else if(discountStyle == 2) {
System.out.println("执行优惠计价方式2的复杂业务逻辑");
} else if(discountStyle == 3) {
System.out.println("执行优惠计价方式3的复杂业务逻辑");
} else {
System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
}
}
可能会遇到的问题
在实际的业务代码中,常见的结构是上面这样的,但是每个if
和if else
之间的代码行数,可能多达几十行,甚至几百行。造成整个计价方法会很庞大。
若干年后如果要调整逻辑或者修改 bug,需要整体阅读一下代码,阅读大量if else
及代码块内的逻辑,调整起来很麻烦。
1.2.2. 使用设计模式方式
使用策略模式,可以使逻辑清晰,将if else
中的逻辑封装到一个个策略中,集中管理,方便阅读及调整;也会简化整体方法及if else
。
接口及数据对象
public interface DiscountCalculateStrategy {
void calculate();
}
public static class DiscountCalculateStrategyA implements DiscountCalculateStrategy {
public void calculate() {
System.out.println("执行优惠计价方式1的复杂业务逻辑");
}
}
public static class DiscountCalculateStrategyB implements DiscountCalculateStrategy {
public void calculate() {
System.out.println("执行优惠计价方式2的复杂业务逻辑");
}
}
public static class DiscountCalculateStrategyC implements DiscountCalculateStrategy {
public void calculate() {
System.out.println("执行优惠计价方式3的复杂业务逻辑");
}
}
public static class DiscountCalculateStrategyDefault implements DiscountCalculateStrategy {
public void calculate() {
System.out.println("执行默认的优惠计价方式的复杂业务逻辑");
}
}
/** 获取计价策略的核心工厂 */
public static class DiscountCalculateStrategyFactory {
public static DiscountCalculateStrategy getDiscountCalculateStrategy(int discountStyle) {
if(discountStyle == 1) {
return new DiscountCalculateStrategyA();
} else if(discountStyle == 2) {
return new DiscountCalculateStrategyB();
} else if(discountStyle == 3) {
return new DiscountCalculateStrategyC();
} else {
return new DiscountCalculateStrategyDefault();
}
}
}
public static class Context {
private DiscountCalculateStrategy strategy;
public DiscountCalculateStrategy getStrategy() {
return strategy;
}
public void setStrategy(DiscountCalculateStrategy strategy) {
this.strategy = strategy;
}
public void calculate() {
strategy.calculate();
}
}
调用方法
public static void main(String[] args) {
// 优惠券类型
int discountStyle = 1;
// 配合工厂模式,屏蔽大量 if else
DiscountCalculateStrategy strategy = DiscountCalculateStrategryFactory
.getDiscountCalculateStrategy(discountStyle);
// 执行对应的计价策略
Context context = new Context();
context.setStrategy(strategy);
context.calculate();
}