命令模式(Command pattern)将”请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。调用者持有的只是命令抽象,不关心命令最终由谁、如何执行。
意图
将命令封装成对象中,以便使用命令来参数化其它对象,或者将命令对象放入队列中进行排队,或者将命令对象的操作记录到日志中,以及支持可撤销的操作。
类图
命令模式有四个角色:
- Command:命令
- Receiver:命令接收者,也就是命令真正的执行者
- Invoker:通过它来调用命令
- Client:可以设置命令与命令的接收者
原文图片丢失,据文字重绘。
classDiagram
class Command {
<<interface>>
+execute()
}
class LightOnCommand {
-Light light
+execute()
}
class LightOffCommand {
-Light light
+execute()
}
class Light {
+on()
+off()
}
class Invoker {
-Command[] onCommands
-Command[] offCommands
+setOnCommand(Command, int)
+setOffCommand(Command, int)
+onButtonWasPushed(int)
+offButtonWasPushed(int)
}
class Client
Command <|.. LightOnCommand
Command <|.. LightOffCommand
LightOnCommand --> Light
LightOffCommand --> Light
Invoker o-- Command
Client ..> Invoker
Client ..> Command
Client ..> Light
实现
设计一个遥控器,可以控制电灯开关。
命令接口:
public interface Command {
void execute();
}
两个具体命令,分别封装”开灯”和”关灯”请求:
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
public class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
接收者,命令真正的执行者:
public class Light {
public void on() {
System.out.println("Light is on!");
}
public void off() {
System.out.println("Light is off!");
}
}
遥控器(Invoker),只依赖 Command 抽象:
/**
* 遥控器
*/
public class Invoker {
private Command[] onCommands;
private Command[] offCommands;
private final int slotNum = 7;
public Invoker() {
this.onCommands = new Command[slotNum];
this.offCommands = new Command[slotNum];
}
public void setOnCommand(Command command, int slot) {
onCommands[slot] = command;
}
public void setOffCommand(Command command, int slot) {
offCommands[slot] = command;
}
public void onButtonWasPushed(int slot) {
onCommands[slot].execute();
}
public void offButtonWasPushed(int slot) {
offCommands[slot].execute();
}
}
public class Client {
public static void main(String[] args) {
Invoker invoker = new Invoker();
Light light = new Light();
Command lightOnCommand = new LightOnCommand(light);
Command lightOffCommand = new LightOffCommand(light);
invoker.setOnCommand(lightOnCommand, 0);
invoker.setOffCommand(lightOffCommand, 0);
invoker.onButtonWasPushed(0);
invoker.offButtonWasPushed(0);
}
}
JDK 中的应用
- java.lang.Runnable
- Netflix Hystrix
- javax.swing.Action