#
Command
#
概念
命令模式(Command Pattern) 是一种行为型设计模式:将一个请求封装为一个对象,从而让你用不同的请求对客户进行参数化;对请求排队或记录请求日志;支持撤销操作(Undo)。
常见应用:
- GUI 按钮点击(按钮绑定命令,而不是具体逻辑)。
- 文本编辑器里的撤销/重做。
- 任务队列。
#
结构
- Command(抽象命令接口): 定义执行命令的接口。
- ConcreteCommand(具体命令类): 绑定接收者,调用接收者的功能。
- Receiver(接收者): 真正执行操作的对象。
- Invoker(调用者): 请求的发送者,调用命令对象来执行请求。
#
例子
// 命令接口
interface Command {
void execute();
void undo();
}
// 接收者:电灯
class Light {
public void on() {
System.out.println("灯已打开");
}
public void off() {
System.out.println("灯已关闭");
}
}
// 具体命令:开灯
class LightOnCommand implements Command {
private final Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
// 具体命令:关灯
class LightOffCommand implements Command {
private final Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
// 调用者:遥控器
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
if (command != null) {
command.execute();
}
}
public void pressUndo() {
if (command != null) {
command.undo();
}
}
}
// 测试类
public class CommandPatternDemo {
public static void main(String[] args) {
Light livingRoomLight = new Light();
Command lightOn = new LightOnCommand(livingRoomLight);
Command lightOff = new LightOffCommand(livingRoomLight);
RemoteControl remote = new RemoteControl();
// 开灯
remote.setCommand(lightOn);
remote.pressButton();
// 撤销(关灯)
remote.pressUndo();
// 关灯
remote.setCommand(lightOff);
remote.pressButton();
// 撤销(开灯)
remote.pressUndo();
}
}
#
优点
- 解耦调用者和接收者。
- 易于扩展新命令。
- 可以实现命令队列、日志记录、撤销/重做。
#
缺点
- 类的数量可能会增加(每个命令都需要一个类)。
#
注意
- 一个文本编辑器需要支持“撤销/重做”、记录操作日志并回放、以及将一组编辑动作打包成宏在其他文档中重复执行。为了统一封装这些操作、便于排队、记录与重放。命令(Command)模式最适合该场景。它将每个编辑动作封装成独立对象,便于排队(任务序列化)、记录操作日志(存储命令历史用于回放)、支持撤销/重做(通过存储命令栈实现状态恢复),并能将多个命令对象组合成宏(宏命令模式)在其他文档中重复执行。