策略模式
策略模式(Strategy)
- 定义一系列算法,把他们一个一个封装起来,并且使它们可互相替换(变化).该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展 ,子类化)
- 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将算法都硬编码到对象中,将会使对象变的异常复杂;而且有时候支持不使用的算法也是一种性能负担
- 策略模式要解决的问题:
- 如何在运行时根据需要透明地 更改对象的算法?
- 将算法与对象本身解耦,从而避免上述问题?
代码例子
常见做法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31//枚举类型来区分不同算法类别
public enum TaxBase {
CN_Tax,
US_Tax,
DE_Tax
}
public class SalesOrder {
TaxBase tax;
public void calculateTax(){
//使用switch来判断不同类别的算法,并进行调用
switch(tax){
case CN_Tax:
//算法一
//.....
break;
case US_Tax:
//算法二
//.....
break;
case DE_Tax:
//算法三
//.....
break;
}
}
}
策略模式改写方案
- Strategy及其子类为组件提供了一系列 可重用的算法 ,从而可以使类型在运行时方便地根据需要在各个算法之间进行切换
- Strategy模式 提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦. 含有许多条件判断语句的代码通常都有Strategy模式.
- 如果Strategy模式对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象的开销.
- PS: 对于后续不需要改变算法的需求,没必要使用策略模式,比如上述代码中枚举对象不会改变,可以保持判断处理逻辑.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46abstract class TaxStraregy {
public abstract double Calculate(Context context);
}
public class CNTax extends TaxStraregy {
public double Calculate(Context context){
//算法一
//.....
}
}
public class USTax extends TaxStraregy {
public double Calculate(Context context){
//算法二
//.....
}
}
public class DETax extends TaxStraregy {
public double Calculate(Context context){
//算法三
//.....
}
}
public class SaleOrder {
TaxStraregy Strategy;
public SaleOrder(TaxStraregy Strategy){
this.Strategy = Strategy;
}
public double CalculateTax(){
Context context;
//多态调用
double result = Strategy.Calculate(context);
}
}