1 定义
策略模式(Strategy Pattern)属于行为型设计模式,它主要对一系列可供选择的算法进行单独封装,不同的算法实现不同的过程,但最终完成着一样的结果。例如现实场景中,商场促销活动中有着多种方案,如:满300减30、满3件打7折等,这些方案都可认为是一种对商品收费的算法,最终的目的都是为了结账。我们消费者根据商品价格和数量可以自由选择哪一种的方式进行结账从而达到价格最大的优惠。
2 实现
策略模式一般包含了3个角色,分别是:
- 上下文环境(Context):用来操作策略的上下文环境。例如上述定义举例的结算。
- 抽象策略(Strategy):定义所有支持的算法的公共接口。例如上述定义举例的促销活动。
- 具体策略(ConcreteStrategy):具体的策略实现,封装了具体的算法或行为,每一种促销方案的具体实现。例如上述定义举例的满300减30的具体促销方案。
上下环境类,内部定义了一个抽象策略对象,维护一个对策略对象的引用:
public class PayContext {
IPromotion mPromotion;
public void setPromotion(IPromotion promotion) {
mPromotion = promotion;
}
public void pay(float price, int count) {
System.out.println("使用了促销方案:" + mPromotion.promotionName() + "最终结算价是:" + mPromotion.calculate(price, count) + "元");
}
}
抽象策略类,它声明了促销名和计算价格的方法:
public interface IPromotion {
String promotionName();
float calculate(float price, int count);
}
具体策略类,分别是满300减30和满3件打7折的具体实现算法:
public class ReturnPromotion implements IPromotion{
@Override
public String promotionName() {
return "满300减30";
}
@Override
public float calculate(float price, int count) {
int discount = 0;
if (price * count >= 300) {
discount = -30;
}
return price * count + discount;
}
}
public class RebatePromotion implements IPromotion {
@Override
public String promotionName() {
return "满3件打7折";
}
@Override
public float calculate(float price, int count) {
float discount = 1;
if (count > 3) {
discount = 0.7f;
}
return price * count * discount;
}
}
客户端:
public class Main {
public static void main(String[] args){
PayContext payContext = new PayContext();
payContext.setPromotion(new ReturnPromotion());
payContext.pay(120, 3);
payContext.setPromotion(new RebatePromotion());
payContext.pay(120, 3);
}
}
输出结果:
使用了促销方案:满300减30最终结算价是:330.0元
使用了促销方案:满3件打7折最终结算价是:360.0元
3 区别
3.1 与状态模式的区别
策略模式和状态模式都是行为型设计模式,他们在使用上非常相似,且实现都是3个角色,上下文、抽象和具体实现。区别在于:
- 策略模式是条件选择,但只会执行一次的选择。例如商场促销活动,我们只能选择一种方案进行结账。
- 状态模式也是条件选择,但会随着状态的改变而进行下一次选择。例如请假流程,根据工作完成状态和请假天数决定审批的流程。
- 如果两种模式要使用同一个例子的话,假如我们去旅游,策略模式是我们在出行前只需选择一种出行的方案直达目的地,可能是坐高铁或者坐飞机;而状态模式是我们先坐高铁到达景点A,然后再坐飞机到景点B。
3.2 与工厂模式的区别
- 工厂模式是创建型设计模式,关注对象的创建;而策略模式是行为型设计模式,关注对象的行为
- 工厂模式主要是为了解决对象的创建,通过共同的接口返回新创建对象;而策略模式是为了解决算法的封装和选择,降低算法之间的耦合,且策略模式往往会搭配工厂模式一起使用。
4 总结
策略模式就是用于算法的封装,当需求中需要在不同的场景应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。其优点在于减少各种算法类与使用算法类之间的耦合,因为每个算法都有自己的类,所以还可以通过自己的接口单独测试来简化单元测试,而且当需要新增策略时不会改动到原有的策略。但也正因为每个算法都有自己的类,也难免因为策略过多而导致代码膨胀。策略模式通常还会结合工厂模式一起使用,从而避免客户端进行过多的条件判断,一般会在Context中封装算法的条件判断选择。