从一个远程控制系统开始
假设我们要做一个远程控制系统,远端可以控制电灯、电子门的开关。远端并不需要知道具体的开关细节,用户只是按下按钮就可以控制电灯、电子门。显然,我们需要使用一种能够将方法调用封装起来的设计模式——Command Pattern。
对于上面的需求,可以写下这样一个程序:
public interface Command
{
public void execute();
}
public class LightOnCommand implements Command
{
Light light;
public LightOnCommand(Light light)
{
this.light = light;
}
public void execute()
{
light.on();
}
}
public class SimpleRemoteControl
{
Command slot;
public SimpleRemoteControl() {}
public void setCommand(Command command)
{
slot = command;
}
public void buttonWasPressed()
{
slot.execute();
}
}
public class RemoteControlTest
{
public static void main(String[] args)
{
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light();
LightOnCommand lightOn = new LightOnCommand(light);
remote.setCommand(lightOn);
remote.buttonWasPressed();
}
}
Command Pattern 的正式定义
现在看看 Command Pattern 的正式定义:
The Command Pattern encapsulates a request as an object, thereby lettting you parameterize other objects with different requests, queue or log requests, and support undoable operations.
一个命令对象封装了请求,这个请求把动作集合全部绑定到一个特定的接收器上。为了达到这样的效果,需要报动作和接收器打包进一个对象,外部只可以通过 excute() 方法执行。从外部来看,其他对象并不知道某个接收器执行了什么操作,调用者只知道如果他们调用 excute() 方法,他们的请求就会被执行。
目前并没有涉及到实现 logs 或支持 undo 的命令,有很多相对直接 Command Pattern 扩展就可以满足。后面的 Meta Command Pattern 可以创建大量命令并一次执行多种命令。
更多应用
- queuing requests
将任务放在队列中,线程选取队列头任务执行,执行完后再回来执行下一个任务。 - logging requests
我们可以在 Command 接口中加两个方法 store() 和 load()。每次执行命令,就存贮一个对应的历史记录;如果系统崩溃,就重载命令。