引入

在之前的文章中我们介绍了常见的设计模式,今天我们来使用 Java 语言对策略模式进行具体实现举例。

实例

策略模式就像为各种情况设计对应的锦囊一样,锦囊可以任意使用,“军师”(编码者)也可以随时替换锦囊的内容。在下面的例子中,我们使用策略模式来对多个if-else的情况来进行优化。

原来的if-else

此处用两数运算来举例,可以看到在原来的设计中,我们需要设立多个if-else分支。

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
private final static String ADD = "+";
private final static String SUBTRACT = "-";
private final static String MULTIPLY = "*";
private final static String DIVIDE = "/";

/**
* 原来的解决流程
*
* @param a 一个
* @param b b
* @param symbol 符号
*/
public static void beforeCount(int a, int b, String symbol) {
Integer result = null;

// 多个if-else的分支判断
if (ADD.equals(symbol)) {
result = a + b;
}
else if (SUBTRACT.equals(symbol)) {
result = a - b;
}
else if (MULTIPLY.equals(symbol)) {
result = a * b;
}
else if (DIVIDE.equals(symbol)) {
result = b == 0? null: a / b;
}

System.out.println(result);
}

使用策略模式后

我们使用一个策略接口作为公共接口(CalculateStrategy接口),然后设立具体的实现类(CalculateAdd、CalculateSubtract、CalculateMultiply、CalculateDivide),在使用只需要创建对应的类即可。在本例中的场景及实现可能略显繁琐,但是在实际应用的时候在遇到多个判断逻辑类似的if-else分支时,可以选用策略模式创建策略接口及类来使用。

策略模式有如下优劣:

优点:

  • 具体实现方式自由
    • 结合Map来简化调用,比如本文中的例子,可以将CalculateXX的实现对象存进一个Map,然后在调用处根据设定的key值直接调用即可
    • 结合模板方法模式来简化策略类的编写,模板方法模式可以将公共的方法或者方法执行逻辑都放在一个模板抽象类或接口(JDK8开始支持的default方法)去预先实现好,这样子类就可以直接使用
  • 避免了多重条件判断
  • 扩展性良好
  • 策略类具体实现方式与客户端无关,其中的具体实现只由当前类知晓

缺点:

  • 要编写多个策略类
  • 所有策略类要向外暴露
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
/**
* 计算器
*
* @author marx
* @date 2022/03/21
*/
static class Calculator {
/**
* 策略
*/
private CalculateStrategy strategy;

public Calculator(CalculateStrategy strategy) {
this.strategy = strategy;
}

/**
* 计算
*
* @param a a
* @param b b
*/
public void count(int a, int b) {
System.out.println(strategy.count(a, b));
}
}

/**
* 计算策略接口,通过实现不同的实现类来给出对应的策略
*
* @author marx
* @date 2022/03/21
*/
interface CalculateStrategy {
/**
* 数
*
* @param a a
* @param b b
* @return {@link Integer}
*/
Integer count(int a, int b);
}

/**
* 计算添加
*
* @author marx
* @date 2022/03/21
*/
static class CalculateAdd implements CalculateStrategy {
@Override
public Integer count(int a, int b) {
return a + b;
}
}

/**
* 计算减去
*
* @author marx
* @date 2022/03/21
*/
static class CalculateSubtract implements CalculateStrategy {
@Override
public Integer count(int a, int b) {
return a - b;
}
}

/**
* 计算乘积
*
* @author marx
* @date 2022/03/21
*/
static class CalculateMultiply implements CalculateStrategy {
@Override
public Integer count(int a, int b) {
return a * b;
}
}

/**
* 计算除法
* 以返回null来代表被除数不合法
*
* @author marx
* @date 2022/03/21
*/
static class CalculateDivide implements CalculateStrategy {
@Override
public Integer count(int a, int b) {
return b == 0? null: a * b;
}
}

参考

策略模式