命令模式
目的
将命令(请求)封装在对象中,以便使用命令来参数化其它对象,或将命令对象放入队列中排队,或将命令对象的操作记录到日志中,以及支持可撤销的操作。
类图
角色
- Command: 命令
- ConcreteCommand:具体命令
- Receiver: 命令接收者:命令真正的执行者
- Invoker: 通过它来调用命令
实现
设计一个遥控器,可以控制电灯开关。
命令
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();
}
}
电灯(Receiver)
public class Light {
public void on() {
System.out.println("Light is on!");
}
public void off() {
System.out.println("Light is off!");
}
}
遥控器(Invoker)
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();
}
}
Client
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);
}
}
优缺点
优点
- 降低对象之间的耦合度。
- 新的命令可以很容易地加入到系统中。
缺点
- 使用命令模式可能会导致某些系统有过多的具体命令类。
使用场景
- 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 需要在不同的时间指定请求、将请求排队和执行请求。
- 需要支持命令的撤销 (Undo) 操作和恢复 (Redo) 操作。
- 需要将一组操作组合在一起,即支持宏命令。
- 认为是命令的地方。比如: GUI 中每个按钮都是一条命令、 CMD。
JDK 中的使用
- java.lang.Runnable
- Netflix Hystrix
- [javax.swing.Action](