通过引入一个命令类,减少发送者和接受者之间的耦合。
0x00 组成部分
- Invoker:调用者,持有命令对象的引用。
- Receiver:接受者,命令的具体执行者。
- Command:抽象命令类,声明了执行请求的方法。
- ConcreteCommand:具体命令类,持有接受者,实现了处理请求的方法。
架构UML图如下。
0x01 实例代码
以MOBA类游戏为例,其中键盘充当调用者,具体游戏角色充当接受者,键盘上的按键充当命令。
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操作。