设计模式之行为型设计模式-策略模式

1. 模式简介

定义了一系列算法、分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。可以避免多重分支的 if...else...switch 语句。属于行为型设计模式

2. 示例代码

  • 支付方式策略
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
/**
* <p>
* 支付策略
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:43
*/
public enum PaymentStrategy {
/**
* 支付宝
*/
ALI_PAY,
/**
* 微信支付
*/
WECHAT_PAY,
/**
* 京东支付
*/
JD_PAY,
/**
* 银联支付
*/
UNION_PAY;

/**
* 支付方式容器池
*/
private static Map<PaymentStrategy, Payment> PAYMENT_POOL = new HashMap<>();

static {
PAYMENT_POOL.put(ALI_PAY, new AliPayment());
PAYMENT_POOL.put(WECHAT_PAY, new WeChatPayment());
PAYMENT_POOL.put(JD_PAY, new JdPayment());
PAYMENT_POOL.put(UNION_PAY, new UnionPayment());
}

/**
* 选择支付方式
*
* @param strategy 支付策略
* @return 支付方式
*/
public static Payment choose(PaymentStrategy strategy) {
Payment payment = PAYMENT_POOL.get(ALI_PAY);

if (PAYMENT_POOL.containsKey(strategy)) {
payment = PAYMENT_POOL.get(strategy);
}

System.out.println("欢迎使用: " + payment.channelName());
return payment;
}
}
  • 支付方式的具体实现
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/**
* <p>
* 支付接口
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:31
*/
public interface Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
String channelName();

/**
* 余额
*
* @return 账户余额
*/
double balance();

/**
* 支付金额
*
* @param money 金额
*/
void pay(double money);
}

/**
* <p>
* 支付宝支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class AliPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "支付宝支付";
}

/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 800;
}

/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}

/**
* <p>
* 京东支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class JdPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "京东支付";
}

/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 500;
}

/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}

/**
* <p>
* 微信支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class WeChatPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "微信支付";
}

/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 1234;
}

/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}

/**
* <p>
* 银联支付
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:38
*/
public class UnionPayment implements Payment {
/**
* 支付渠道
*
* @return 支付渠道
*/
@Override
public String channelName() {
return "银联支付";
}

/**
* 余额
*
* @return 账户余额
*/
@Override
public double balance() {
return 10;
}

/**
* 支付金额
*
* @param money 金额
*/
@Override
public void pay(double money) {
if (balance() < money) {
System.err.println("余额不足,当前余额:" + balance());
} else {
System.out.println("支付成功,交易金额:" + money);
}
}
}
  • 测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* <p>
* 策略模式,测试类
* </p>
*
* @author yangkai.shen
* @date Created in 2019/8/28 14:54
*/
public class PatternTest {
public static void main(String[] args) {
Payment payment = PaymentStrategy.choose(PaymentStrategy.ALI_PAY);
payment.pay(200);

System.out.println("--------------------");

payment = PaymentStrategy.choose(PaymentStrategy.UNION_PAY);
payment.pay(200);
}
}
  • 测试结果
1
2
3
4
5
欢迎使用: 支付宝支付
支付成功,交易金额:200.0
--------------------
欢迎使用: 银联支付
余额不足,当前余额:10.0

3. UML 图例

设计模式-行为型设计模式-策略模式

4. 应用

1
2
3
4
5
6
7
8
9
10
11
12
// JDK 的 Comparator 接口,比如:
// java.util.Arrays#parallelSort(int[], int, int)
// java.util.TreeMap#TreeMap(java.util.Comparator<? super K>)

// Spring 的 Resource 接口,比如:
// ClassPathResource
// UrlResource
// FileUrlResource
// FileSystemResource
// ClassPathResource
// ByteArrayResource
// InputStreamResource

5. 场景

  • 假如系统中有很多类,而他们的区别仅仅在于他们的行为不同。
  • 一个系统需要动态地在几种算法中选择一种。

6. 优缺点

优点: 1、策略模式符合开闭原则。2、避免使用多重条件转移语句,如if…else…语句、switch语句。3、使用策略模式可以提高算法的保密性和安全性。

缺点: 1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类。 2、代码中会产生非常多策略类,增加维护难度。

7. 完整代码地址

https://github.com/xkcoding/design-pattern/tree/master/src/main/java/com/xkcoding/design/pattern/behavioral/strategy

-------------本文结束  感谢您的阅读-------------
xkcoding wechat
欢迎来我的公众号「xkcoding小凯扣丁」逛逛
o(╯□╰)o 赞助一杯咖啡 ~~