策略(Strategy)模式
# 策略(Strategy)模式
策略(Strategy)模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。属于对象行为模式。

抽象策略(Strategy)类:公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
public interface GameStrategy {
// 战斗策略
void warStrategy();
}
1
2
3
4
2
3
4
具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
public class SteadyStrategy implements GameStrategy{
@Override
public void warStrategy() {
System.out.println("各路小心...及时支援..");
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
public class RandomStrategy implements GameStrategy{
@Override
public void warStrategy() {
System.out.println("大乱斗");
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
环境(Context)类:持有一个策略类的引用,最终给客户端调用。
/**
* 环境类
*/
public class TeamGNR {
// 抽取游戏策略算法,并进行引用
private GameStrategy gameStrategy;
public void setGameStrategy(GameStrategy gameStrategy) {
this.gameStrategy = gameStrategy;
}
public void startGame(){
System.out.println("游戏开始");
//游戏策略
gameStrategy.warStrategy();
System.out.println("win...");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
测试
public class MainTest {
public static void main(String[] args) {
TeamGNR teamGNR = new TeamGNR();
// teamGNR.setGameStrategy(new SteadyStrategy());
teamGNR.setGameStrategy(new RandomStrategy());
teamGNR.startGame();
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 应用场景
什么场景用到?
- 使用策略模式可以避免使用多重条件语句,如 if...else 语句、switch...case 语句
- 什么是 Spring 的 InstantiationStrategy
- 线程池拒绝策略
JDK 的 Arrays 的 Comparator 就使用了策略模式

public static void main(String[] args) {
/ TODOAuto - generated method stub
//数组
Integer[] data = { 9, 1, 2, 8, 4, 3 };
// 实现降序排序,返回-1 放左边,1 放右边,0 保持不变
// 说明
// 1. 实现了 Comparator 接口(策略接口) , 匿名类 对象 new Comparator<Integer>(){..}
// 2. 对象 new Comparator<Integer>(){..} 就是实现了 策略接口 的对象
// 3. public int compare(Integer o1, Integer o2){} 指定具体的处理方式
Comparator<Integer> comparator = new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
if (o1 > o2) {
return -1;
} else {
return 1;
}
};
};
// 说明
/* public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a); //默认方法
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c); //使用策略对象 c
else
// 使用策略对象 c
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}*/
//方式 1
Arrays.sort(data, comparator);
System.out.println(Arrays.toString(data)); // 降序排序
//方式 2- 同时 lambda 表达式实现 策略模式
Integer[] data2 = { 19, 11, 12, 18, 14, 13 };
Arrays.sort(data2, (var1, var2) -> {
if (var1.compareTo(var2) > 0) {
return -1;
} else {
return 1;
}
});
System.out.println("data2=" + Arrays.toString(data2));
}
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
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
# 注意事项和细节
- 策略模式的关键是:分析项目中变化部分与不变部分
- 策略模式的核心思想是:多用组合 / 聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性
- 体现了 “对修改关闭,对扩展开放” 原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可,避免了使用多重转移语句(if..else if..else)
- 提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展
- 需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞
编辑 (opens new window)
上次更新: 2023/12/13, 06:06:02