第十一章 让程序畅通执行——命令模式
1.定义
将一个请求封装成一个对象,让用户使用不同的请求把客户端参数化,对请求进行排队或者记录请求日志,并支持可撤销的操作。
2.使用场景
1).需要抽象出待执行的行为,然后以参数的形式提供出来时。
2).在不同的时刻指定、排列和执行请求时。
3).需要支持取消操作时。
4).支持修改日志功能,当系统崩溃时,这些修改可以被重做一遍时。
5).需要支持事务操作时。
3.简单实现
以一个俄罗斯方块游戏机为例,这个游戏机有“左移”,“右移”,“变换形状”,“快速下落”四个按键。
首先定义一个俄罗斯方块游戏机类:
public class TetrisMachine {
public void up() {
System.out.println("变换形状");
}
public void down() {
System.out.println("快速下落");
}
public void left() {
System.out.println("左移");
}
public void right() {
System.out.println("右移");
}
}
定义一个命令接口:
public interface Command {
void execute();
}
public class LeftCommand implements Command {
private TetrisMachine mTetrisMachine;
public LeftCommand(TetrisMachine tetrisMachine) {
this.mTetrisMachine = tetrisMachine;
}
@Override
public void execute() {
mTetrisMachine.left();
}
}
public class RightCommand implements Command {
private TetrisMachine mTetrisMachine;
public RightCommand(TetrisMachine tetrisMachine) {
this.mTetrisMachine = tetrisMachine;
}
@Override
public void execute() {
mTetrisMachine.right();
}
}
public class UpCommand implements Command {
private TetrisMachine mTetrisMachine;
public UpCommand(TetrisMachine tetrisMachine) {
this.mTetrisMachine = tetrisMachine;
}
@Override
public void execute() {
mTetrisMachine.up();
}
}
public class DownCommand implements Command {
private TetrisMachine mTetrisMachine;
public DownCommand(TetrisMachine tetrisMachine) {
this.mTetrisMachine = tetrisMachine;
}
@Override
public void execute() {
mTetrisMachine.down();
}
}
接下来定义一个按键的类,存放了每一条命令实现类的实例,定义了调用每条命令的方法:
public class Buttons {
private LeftCommand leftCommand;
private RightCommand rightCommand;
private UpCommand upCommand;
private DownCommand downCommand;
public Buttons(LeftCommand leftCommand, RightCommand rightCommand, UpCommand upCommand, DownCommand downCommand) {
this.leftCommand = leftCommand;
this.rightCommand = rightCommand;
this.upCommand = upCommand;
this.downCommand = downCommand;
}
public void left() {
leftCommand.execute();
}
public void right() {
rightCommand.execute();
}
public void up() {
upCommand.execute();
}
public void down() {
downCommand.execute();
}
}
接下来就可以在客户端调用了:
TetrisMachine mTetrisMachine = new TetrisMachine();
Buttons buttons = new Buttons(new LeftCommand(mTetrisMachine)
, new RightCommand(mTetrisMachine)
, new UpCommand(mTetrisMachine)
, new DownCommand(mTetrisMachine));
buttons.left();
buttons.right();
buttons.up();
buttons.down();
上面的例子不禁让我疑惑,明明可以直接调用的,却要做得很复杂:
TetrisMachine mTetrisMachine = new TetrisMachine();
mTetrisMachine.left();
mTetrisMachine.right();
mTetrisMachine.up();
mTetrisMachine.down();
然后我释怀了,简单对于开发者是方便了,但是如果你突然不负责这个项目了,这样直接的调用,对于后面接手的开发者可不是那么好改的,牵一发而动全身,使用命令模式是为了简化逻辑而增加了操作。
4.总结
几乎所有的设计模式都有一个通病,就是类的增多,命令模式更是体现得淋漓尽致,但是为了解耦,这不可避免。
优点:
1).降低耦合性,提高可控性和可扩展性。
2).可以实现命令记录的功能,能方便的知道刚刚执行过哪些命令,并可在需要的时候恢复。
缺点:
1).会创建大量衍生的类。