介绍
将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化,对请求排队或者记录请求日志,以及支持可撤销的操作,
应用场景
- 需要抽象出待执行的动作,然后以参数的形式体统出来——类似过程设计中的回调机制
- 在不同的时刻指定、排序和执行的请求,一个命令对象可以有与初始请求无关的生存期
- 需要支持取消操作
- 支持修改日志
- 需要支持事务
UML
具体代码实现
以俄罗斯方块中的按键为例
- 接收者角色
public class TetrisMachine {
public void toLeft() {
System.out.println("向左");
}
public void toRight() {
System.out.println("向右");
}
public void fastToBottom() {
System.out.println("快速下降");
}
public void transform() {
System.out.println("改变形状");
}
}
- 抽象命令接口
public interface Command {
void execute();
}
- 具体命令类
public class FallCommand implements Command {
private TetrisMachine machine;
public FallCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.fastToBottom();
}
}
public class LeftCommand implements Command {
private TetrisMachine machine;
public LeftCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.toLeft();
}
}
public class RightCommand implements Command {
private TetrisMachine machine;
public RightCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.toRight();
}
}
public class TransformCommand implements Command {
private TetrisMachine machine;
public TransformCommand(TetrisMachine machine) {
this.machine = machine;
}
@Override
public void execute() {
machine.transform();
}
}
- 请求角色
public class Buttons {
private LeftCommand leftCommand;
private RightCommand rightCommand;
private FallCommand fallCommand;
private TransformCommand transformCommand;
public void setLeftCommand(LeftCommand leftCommand) {
this.leftCommand = leftCommand;
}
public void setRightCommand(RightCommand rightCommand) {
this.rightCommand = rightCommand;
}
public void setFallCommand(FallCommand fallCommand) {
this.fallCommand = fallCommand;
}
public void setTransformCommandl(TransformCommand transformCommand) {
this.transformCommand = transformCommand;
}
public void toLeft() {
leftCommand.execute();
}
public void toRight() {
rightCommand.execute();
}
public void fallTo() {
fallCommand.execute();
}
public void transform() {
transformCommand.execute();
}
}
- 客户端
public static void main(String[] args) {
Buttons buttons = new Buttons();
TetrisMachine machine = new TetrisMachine();
LeftCommand leftCommand = new LeftCommand(machine);
RightCommand rightCommand = new RightCommand(machine);
FallCommand fallCommand = new FallCommand(machine);
TransformCommand transformCommand = new TransformCommand(machine);
buttons.setFallCommand(fallCommand);
buttons.setRightCommand(rightCommand);
buttons.setTransformCommandl(transformCommand);
buttons.setLeftCommand(leftCommand);
buttons.toRight();
buttons.toLeft();
}
- 输出结果
其实到这里会有很多读者会感到疑惑,明明可以只用一个类就解决的问题,硬是被解耦成多个部分,增加代码的复杂度,为什么呢?
其实是为了设计模式的一个重要原则:对修改关闭,对扩展开放,这里大家慢慢体会。
总结
在命令模式中充分体现了几乎所有模式的通病,就是类的膨胀,大量衍生类的创建,这是一个不可避免的问题,但是给我们带来的好处也是非常多,更弱的耦合性,更灵敏的控制性,以及更好的扩展性,不过在实际开发中是否使用命令模式是要好好斟酌的。