命令模式

简介

命令模式,通过对请求命令的封装,对命令的请求方和执行方进行解偶,书本上举例了顾客点餐的过程,顾客下单点餐,然后服务员将菜单拿给厨师制作,通过菜单实现了顾客与服务员,服务员与厨师之间的解偶。

实现

定义一个命令接口,接口只有execute方法

1
2
3
4
public interface Command {

void execute();
}

对命令的一种实现,比如:打开电灯泡,这里封装了灯泡对象

1
2
3
4
5
6
7
8
9
10
11
12
13
public class LightOnCommand implements Command {

Light light;

public LightOnCommand(Light light) {
this.light = light;
}

@Override
public void execute() {
light.on();
}
}

遥控器可以执行命令对象,至于命令具体是怎么执行,我不需要关心,因为封装在请求里面了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class SimpleRemoteControl {

Command slot;

public SimpleRemoteControl() {
}

public void setCommand(Command command) {
this.slot = command;
}

public void buttonWasPressed() {
slot.execute();

}
}

对遥控器进行简单测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class SimpleRemoteControlTest extends AbstractTest {

SimpleRemoteControl simpleRemoteControl = null;
Light light = null;
Command command = null;

@Before
public void setUp() throws Exception {
simpleRemoteControl = new SimpleRemoteControl();
light = new Light();
command = new LightOnCommand(light);
}

@Test
public void buttonWasPressed() {
simpleRemoteControl.setCommand(command);
simpleRemoteControl.buttonWasPressed();
}
}

通过测试我们看到,遥控器可以set不同的命令,至于命令的接收者封装在了命令的实现当中,遥控器漠不关心,只是执行了command.execute()方法,具体干嘛了也不知道,这样实现了客户请求与请求执行之间的解偶,我们的类关系图如下:

定义

在书上定义为:

将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

类图为:

应用

在实际的开发中,我们用到命令模式的地方有:线程池、工作队列。

命令可以支持撤销操作,所以一个常见的用于日志请求,比如电脑死机数据恢复处理,mysql日志备份和还原。