设计模式之命令模式(卷十四)

设计模式之命令模式。

通过引入一个命令类,减少发送者和接受者之间的耦合。

0x00 组成部分

  • Invoker:调用者,持有命令对象的引用。
  • Receiver:接受者,命令的具体执行者。
  • Command:抽象命令类,声明了执行请求的方法。
  • ConcreteCommand:具体命令类,持有接受者,实现了处理请求的方法。

架构UML图如下。

0x01 实例代码

以MOBA类游戏为例,其中键盘充当调用者,具体游戏角色充当接受者,键盘上的按键充当命令。

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
package com.kkk.pattern.command1;

import java.util.HashMap;
import java.util.Map;

/**
* HHKB键盘,充当调用者。
* Created by z3jjlzt on 2018/1/12.
*/

public class HHKB {
//键盘上持有一系列按键集合。
private static final Map<String, Skill> btns = new HashMap<>();

public HHKB addBtn(String k, Skill v) {
btns.put(k, v);
return this;
}

public void removeBtn(String k) {
btns.remove(k);
}

public void pressBtn(String btn) {
if (btns.containsKey(btn)){
btns.get(btn).play();
} else {
System.out.println(btn + "技能冷却中!!");
}
}
}

/**
* LOLRole,充当技能的接受者。
* Created by z3jjlzt on 2018/1/12.
*/

public class LOLRole {

private String name;

public LOLRole(String name) {
this.name = name;
}

public void action(String action) {
System.out.println(name + "释放了 " + action + "技能");
}
}

/**
* 技能接口,充当抽象命令类。
* Created by z3jjlzt on 2018/1/12.
*/

public abstract class Skill {
//持有接受者引用。
protected LOLRole LOLRole;

protected void setLOLRole(LOLRole LOLRole) {
this.LOLRole = LOLRole;
}

public abstract void play();
}

/**
* Q技能,充当具体命令类。
* Created by z3jjlzt on 2018/1/12.
*/

public class SkillQ extends Skill{
@Override
public void play() {
LOLRole.action("Q");
}
}

public class Client {
public static void main(String[] args) {
Skill q, w, e, r;
q = new SkillQ();
w = new SkillW();
e = new SkillE();
r = new SkillR();
LOLRole river = new LOLRole("River");
q.setLOLRole(river);
w.setLOLRole(river);
e.setLOLRole(river);
r.setLOLRole(river);
HHKB hhkb = new HHKB();
hhkb.addBtn("q", q)
.addBtn("w", w)
.addBtn("e", e)
.addBtn("r", r);
hhkb.pressBtn("e");
hhkb.pressBtn("r");
hhkb.pressBtn("w");
hhkb.pressBtn("q");
hhkb.pressBtn("r");
hhkb.removeBtn("w");
hhkb.pressBtn("w");
}
}
结果:
River释放了 E技能
River释放了 R技能
River释放了 W技能
River释放了 Q技能
River释放了 R技能
w技能冷却中!!

0xff 总结

  • 优点:降低调用者和接受者的耦合,添加新的命令符合开闭原则,为undo提供了解决方法。
  • 缺点:导致具体命令类膨胀。
  • 适用场景:系统需要降低调用者和接受者的耦合,提供undo操作。