现实中,一件事可能会有很多种方式实现,但总有一种最高效的方式。
为了让问题得以解决,我们将可以解决问题的一个或多个方法定义成一个“算法群”;其中的每一个方法对应一组具体的算法,我们将其称之为“策略”。
《设计模式:可复用面向对象软件的基础》中的介绍:
“定义一系列算法,将他们一一封装,并使他们可以相互替换”
“本模式使得算法能独立于使用它的客户而变化”
实现的时候把不同组的算法封装在不同的类里。
结构图
以上,可见策略模式包括:
Context
- 环境类,上层访问策略的入口
- 维护一个对抽象策略 Strategy 对象的引用
- 通过一个 ConcreteStrategy 来配置
- 可定义一个接口让 Strategy 访问它的数据
Strategy
- 抽象策略类
- 定义所有所支持的算法的公共接口,Context 通过该接口调用某个具体策略类 ConcreteStrategy 定义的算法
ConcreteStrategy
- 具体策略类
- 封装具体的算法实现
例图:
代码示例
角色代码
1 | // Context 持有对 Strategy 的引用,并且提供了调用策略的方法 |
1 | // 抽象策略类,定义了策略的方法 |
1 | // 具体策略角色类 |
调用代码
1 | // 客户端 |
特点
- 一系列算法组成一个策略
- 这些算法都实现了相同的接口或继承了相同的抽象类
优缺点
优点:
- 算法可以自由切换。
- 避免使用多重条件判断,一定程度杜绝了 if-else 带来的代码不美观。
- 扩展性非常良好;如需新的策略,只需扩展原有抽象策略接口即可。
缺点:
- 策略类比较容易增多。
- 所有策略类都需要对外暴露
策略模式结合简单工厂模式的应用
应用于:商店促销活动
策略上下文 Context:1
2
3
4
5
6
7
8
9
10
11public class CashContext {
CashSuper cs = null;
public CashContext(CashSuper csuper) {
this.cs = csuper;
}
public double getResult(double money) {
return cs.acceptCash(money);
}
}
策略: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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64public interface CashSuper {
/**
* 抽象策略,计算实收的费用
* @param money 应收金额
* @return 实收金额
*/
double acceptCash(double money);
}
// 正常收费策略
public class CashNormal implements CashSuper {
public double acceptCash(double money) {
return money;
}
}
// 打折策略
public class CashRebate implements CashSuper {
private double moneyRebate;
/**
* @param moneyRebate 折扣
*/
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
public double acceptCash(double money) {
return money * (moneyRebate / 10);
}
}
// 满减策略
public class CashRefund implements CashSuper {
/**
* 应收金额
*/
private final double moneyCondition;
/**
* 返利金额
*/
private double moneyRefund;
public CashRefund(double moneyCondition, double moneyRefund) {
this.moneyCondition = moneyCondition;
this.moneyRefund = moneyRefund;
}
public double acceptCash(double money) {
if (money >= moneyCondition) {
money -= moneyRefund;
}
return money;
}
}
简单工厂:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class CashFactory {
public static CashSuper createCashAccept(String cashType) {
CashSuper cs = null;
switch (cashType.toLowerCase()) {
case "20discount": // 八折
cs = new CashRebate(8);
break;
case "refund100for300": // 满 300 减 100
cs = new CashRefund(300, 100);
break;
case "normal": // 正常收费
default:
cs = new CashNormal();
break;
}
return cs;
}
}
然后就是简单的调用:1
2
3CashSuper cs = CashFactory.createCashAccept("20discount"); // 打八折
double result = cs.acceptCash(300);
System.out.println(result); // 240
策略的高级玩法:反射实现
1 | public class CashContextReflect { |