15.设计模式-COMMAND(命令)
一、模式定义与核心思想
命令模式是一种行为型设计模式,其核心目标是通过将请求封装为独立对象,实现请求发送者与执行者的解耦,支持请求的参数化、队列化、撤销与重做。该模式通过将操作抽象为可存储、传递的对象,赋予系统以下核心能力:
- 解耦请求与执行:客户端无需知道具体执行逻辑(如餐厅点餐时顾客与厨师的解耦)。
- 事务管理:支持操作的回滚、重试(如文本编辑器的撤销功能)。
- 灵活扩展:动态添加新命令,支持宏命令组合(如智能家居的自动化场景)。
- 异步处理:实现请求的延迟执行与队列调度(如任务队列系统)。
经典场景:
- 文本编辑器的撤销/重做堆栈
- GUI按钮与菜单的事件绑定
- 智能家居的遥控器指令系统
- 分布式系统的命令日志与事务补偿
二、模式组成与UML类图
核心角色
- Command(命令接口):
-
- 声明执行操作的统一接口(如
execute()、undo())。
- 声明执行操作的统一接口(如
- ConcreteCommand(具体命令):
-
- 实现命令接口,关联接收者对象(如
LightOnCommand封装开灯操作)。
- 实现命令接口,关联接收者对象(如
- Receiver(接收者):
-
- 实际执行业务逻辑的对象(如电灯、数据库连接池)。
- Invoker(调用者):
-
- 触发命令执行(如遥控器按钮、GUI事件处理器)。
- Client(客户端):
-
- 组装命令对象与接收者的关系1****8。
UML类图
classDiagram
class Command {
<<interface>>
+execute()
+undo()
}
class ConcreteCommand {
-receiver: Receiver
+execute()
+undo()
}
class Receiver {
+action()
}
class Invoker {
-command: Command
+setCommand()
+executeCommand()
}
class Client
Command <|.. ConcreteCommand
ConcreteCommand --> Receiver
Invoker --> Command
Client --> ConcreteCommand
Client --> Receiver

三、代码实现示例
场景:实现支持撤销操作的智能家居灯光控制
// 1. 接收者(电灯)
class Light {
void turnOn() { System.out.println("灯光开启"); }
void turnOff() { System.out.println("灯光关闭"); }
}
// 2. 命令接口
interface Command {
void execute();
void undo();
}
// 3. 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) { this.light = light; }
@Override
public void execute() { light.turnOn(); }
@Override
public void undo() { light.turnOff(); }
}
// 4. 调用者(遥控器)
class RemoteControl {
private Command command;
private Stack<Command> history = new Stack<>();
public void setCommand(Command cmd) { this.command = cmd; }
public void pressButton() {
command.execute();
history.push(command);
}
public void pressUndo() {
if (!history.isEmpty()) {
Command lastCmd = history.pop();
lastCmd.undo();
}
}
}
// 5. 客户端调用
public class Client {
public static void main(String[] args) {
Light light = new Light();
Command cmd = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(cmd);
remote.pressButton(); // 开灯
remote.pressUndo(); // 关灯(撤销)
}
}
四、工业级源码应用
- Java Swing事件处理
- 每个按钮点击事件(
ActionListener)本质是命令对象,将GUI操作与业务逻辑解耦。
button.addActionListener(e -> service.doSomething()); // Lambda表达式封装命令
- Spring框架事务管理
-
@Transactional注解通过AOP生成事务命令对象,封装数据库的commit/rollback操作。
- MyBatis Mapper接口
-
- 动态代理生成
Mapper接口的实现类,将SQL执行封装为命令对象。
- 动态代理生成
- 文本编辑器撤销功能
-
- 如IntelliJ IDEA通过
UndoManager维护命令栈,支持多级撤销。
- 如IntelliJ IDEA通过
- 游戏引擎技能系统
-
- 魔兽世界的技能快捷键绑定命令对象,支持技能队列与取消施法。
五、模式对比与最佳实践
| 维度 | 命令模式 | 策略模式 |
|---|---|---|
| 关注点 | 请求封装与生命周期管理 | 算法替换 |
| 核心价值 | 解耦调用与执行,支持事务 | 动态切换行为策略 |
| 典型场景 | 撤销/重做、异步队列 | 支付方式选择、排序算法 |
最佳实践建议:
- 轻量化命令对象:避免在命令中存储过多状态(优先使用接收者状态)。
- 组合命令:通过
MacroCommand实现批处理操作。 - 线程安全:多线程环境下需对命令队列加锁(如
BlockingQueue)。
总结
命令模式通过操作对象化的设计哲学,在GUI框架、事务系统等领域展现出强大的灵活性。其核心价值在于将请求的发起与执行分离,使得系统能够优雅地支持撤销、重做、事务管理等高级特性。开发者应重点把控命令对象的生命周期与状态管理,结合具体场景选择静态代理或动态代理实现方式,从而构建出高扩展、易维护的系统架构。

浙公网安备 33010602011771号