1、什么是策略模式?
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
2、解决了什么问题?
在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
3、有什么优缺点?
-
优点:
- 1、算法可以自由切换。
- 2、避免使用多重条件判断。
- 3、扩展性良好。
-
缺点:
- 1、策略类会增多。
- 2、所有策略类都需要对外暴露。
4、如何解决问题?
将这些算法封装成一个一个的类,实现同一个接口,任意地替换。
5、实例
商品促销结算时,可能会有不同的结算方式,如:
- 方式A: 满200-88
- 方式B:每满100-50
- 方式C:会员打88折
若有一个订单结算的service,那么应该如何写?
public class PayService{
public double calculate(Order order,String method){
//计算订单的价格,如何写?
...
}
}
很容易的就可以想到使用if…else或者witch…case:
public double calculate(Order order,String method){
if ("A".equals(method)){
//方式A的计算方式
......
}else if ("B".equals(method)){
//方式B的计算方式
......
}else if ("C".equals(method)){
//方式B的计算方式
......
}else{
//老板不开心,今天不搞促销。
}
}
或者
public double calculate(Order order,String method){
switch(method){
case "A":
//方式A的计算方式
......
break;
case "B":
//方式B的计算方式
......
break;
case "C":
//方式C的计算方式
......
break;
default :
//老板不开心,不搞促销
}
}
这样的代码维护起来比较麻烦,不容易扩展。
进行优化:把A、B、和C计算方式方法抽出来。
但是我们还可以引入策略模式进行优化:
首先创建一个订单处理的接口:
public interface CalculateService{
double calculate(Order order);
}
方式A的处理算法:
public class A implements CalculateService{
double calculate(Order order){
//方式A的处理方法
...
}
}
方式B的处理方法
public class B implements CalculateService{
double calculate(Order order){
//方式B的处理方法
....
}
}
方式C的处理方法
public class C implements CalculateService{
double calculate(Order order){
//方式C的处理方法
}
}
因此,在orderService中可以做如下改变:
public double calculate(Order order,String method){
switch(method){
case "A":
new A().calculate(order);
break;
case "B":
new B().calculate(order);
break;
case "C":
new C().calculate(order);
break;
default :
//老板不开心,不搞促销
}
}
这样在后期的维护过程中,会比较易于维护。
6、还有改进的地方吗?
有,可以使用工厂模式产生实例。
public class MethodFactory{
public CalculateService getMethod(String method){
switch(method){
case "A":
new A();
break;
case "B":
new B();
break;
case "C":
new C();
break;
default :
//老板不开心,不搞促销
}
}
}
那么service中的方法将会有如下变化:
public class PayService{
private MethodFactory methodFactory;
public double calculate(Order order,String method){
return methodFactory.getMethod(method).calculate(order);
}
}
7、注意事项:
- 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。