前面聊过模版方法,在一个算法中某步骤有多套实现时,可以很有效替换算法步骤。那如果在一套代码中有多种策略呢?更换策略是否还要更改原有的代码?这次说说策略模式。


  • 举例

OK,我们现在有个ChooseStrategy类要完成某个功能,只需调用execute()即可,该功能有用到两种策略分别是SimpleStrategySpecialStrategy类。

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
public class ChooseStrategy {
private Strategy strategy = null;
public ChooseStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void execute() {
// ... code ...
if(this.strategy != null) {
this.strategy.fuck();
} else {
throw new Exception();
}
// ... code ...
}
}
public interface Strategy {
void fuck();
}
public class SimpleStrategy implements Strategy {
public void fuck() {
System.out.println("这是个简单的策略!");
}
}
public class SpecialStrategy implements Strategy {
public void fuck() {
System.out.println("这是个特殊的策略!");
}
}

在对每种策略都了如指掌的情况下,我们能根据不同情况设置不同的策略。

1
2
3
4
5
6
7
8
9
10
public class StrategyPattern {
public static void main(String[] args) {
ChooseStrategy choose = new ChooseStrategy(new SimpleStrategy());
choose.execute();
choose.setStrategy(new SpecialStrategy());
choose.execute();
choose.setStrategy(null);
choose.execute();
}
}

  • JDK中的策略模式

java.util.Collections类的静态方法sort(List<T> list, Comparator<? super T> c)就是策略模式,实现Comparator接口即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
ListIterator i = list.listIterator();
for (int j=0; j<a.length; j++) {
i.next();
i.set(a[j]);
}
}
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}

实现Comparator接口,跟模板方法很相似,示例:

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
class SizeComparator implements Comparator<Dick> {
@Override
public int compare(Dick o1, Dick o2) {
return o2.getSize() - o1.getSize();
}
}
class Dick {
private String name;
private int size;
public Dick(String name, int size) {
super();
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
@Override
public String toString() {
return "Dick [name=" + name + ", size=" + size + "cm]";
}
}
public class TestComparator {
public static void main(String[] args) {
Dick[] fuckers = {new Dick("张三", 17),
new Dick("李四", 14),
new Dick("王五", 29),
new Dick("老六", 22),
new Dick("赵七", 11)};
List<Dick> dicks = new ArrayList<Dick>();
Arrays.sort(fuckers);
for(Dick fucker : fuckers)
dicks.add(fucker);
Collections.sort(dicks, new SizeComparator());
// [Dick [name=王五, size=29cm], Dick [name=老六, size=22cm], Dick [name=张三, size=17cm], Dick [name=李四, size=14cm], Dick [name=赵七, size=11cm]]
System.out.println(dicks);
}
}