Design Patterns(二十一) Strategy

Strategy Design Pattern is a type of behavioral design pattern that encapsulates a “family” of algorithms and selects one from the pool for use during runtime. The algorithms are interchangeable, meaning that they are substitutable for each other.

前言

    策略模式(Strategy Pattern)定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

策略模式

基本介绍:

1) 策略模式(Strategy Pattern)中,定义算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户;
2) 这算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类(定义了策略接口);第三、多用组 合/ 聚合,少用继承(客户通过组合方式使用策略 )。

角色介绍:

1)抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现;
2)具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现;
3)环境(Context)类:持有一个策略类的引用,最终给客户端调用。

策略模式-UML图:





策略模式-实例图:


代码:

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* @Auther: Arsenal
* @Date: 2020-03-21 18:00
* @Description: 策略模式
*/
public class Strategy {
public static void main(String[] args) {
String type = "满300减100";
CashContext cc = null;

switch (type) {
case "正常收费":
cc = new CashContext(new CashNormal());
break;
case "满300减100":
cc = new CashContext(new CashReturn(300, 100));
break;
case "打8折":
cc = new CashContext(new CashRebate(0.8));
break;
}

double resultPrice = cc.GetResult(520);
System.out.println("最终的价格是:" + resultPrice);

}
}

/**
* Strategy类
*/
abstract class CashSuper {
/**
* 现金收取超类方法,传入原价,返回当前价
*/
public abstract double acceptCash(double money);
}

/**
* ConcreteStrategy类
*/
class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
// 正常收费,返回原价
return money;
}
}

/**
* ConcreteStrategy类
*/
class CashRebate extends CashSuper {

private double moneyRebate = 1;

public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}

@Override
public double acceptCash(double money) {
// 正常收费,返回原价
return money * moneyRebate;
}
}

/**
* ConcreteStrategy类
*/
class CashReturn extends CashSuper {

private double moneyCondition = 0;// 满足的条件
private double moneyReturn = 0;//返利

public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}

@Override
public double acceptCash(double money) {
double result = money;
if (money >= moneyCondition) {
result = money - Math.floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}

/**
* Context类
*/
class CashContext {
private CashSuper cs;

public CashContext(CashSuper cs) {
this.cs = cs;
}

public double GetResult(double money) {
return cs.acceptCash(money);
}
}

总结

策略模式的注意事项和细节:

1) 策略模式的关键是:分析项目中变化部分与不变部分;
2) 策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性;
3) 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为)即可,避免了使用多重转移语句(if..else if..else);
4) 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的Strategy类中使得你可以独立于其Context改变它,使它易于切换、易于理解、易于扩展;
5) 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞大。

延伸

    深入解析策略模式
    策略模式-菜鸟教程
    策略模式(策略设计模式)详解
    Design Patterns - Strategy Pattern
    尚硅谷Java设计模式,韩顺平图解java设计模式

Content
  1. 1. 前言
  2. 2. 策略模式
  3. 3. 总结
  4. 4. 延伸