1. 命令模式概述:当"遥控器"遇上编程
命令模式(Command Pattern)是我在十年代码生涯中频繁使用的设计模式之一,它完美诠释了"封装变化"这一设计原则。想象你手中的电视遥控器——按键本身并不实现功能,而是将"换台"、"调音量"等操作封装成独立命令对象。这正是命令模式的核心:将请求封装为对象,使你可以参数化客户端与不同请求。
在Java标准库中,Runnable接口就是命令模式的经典实现。我们把要执行的操作封装在run()方法里,这个Runnable对象可以传递给线程、线程池或任何需要执行逻辑的组件。这种解耦带来的灵活性在实际开发中价值连城。
关键认知:命令模式不是简单的"把方法包装成对象",而是建立一套可扩展、可撤销、可队列化的请求处理机制
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 模式结构与核心组件
2.1 UML类图解析
标准的命令模式包含以下角色(以智能家居控制系统为例):
code复制┌─────────────┐ ┌─────────────┐
│ Client │ │ Invoker │
└─────────────┘ └─────────────┘
| |
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Command │<───────│ Concrete │
│ Interface │ │ Command │
└─────────────┘ └─────────────┘
▲ |
| ▼
┌─────────────┐ ┌─────────────┐
│ Receiver │ │ Receiver │
└─────────────┘ └─────────────┘
2.2 角色职责详解
-
Command(命令接口):
- 定义执行操作的接口(通常为execute())
- 示例代码:
java复制public interface Command { void execute(); void undo(); // 可选撤销操作 }
-
ConcreteCommand(具体命令):
- 绑定接收者与动作
- 典型实现:
java复制public class LightOnCommand implements Command { private Light light; // Receiver public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOn(); // 委托给Receiver } }
-
Invoker(调用者):
- 持有命令对象并触发执行
- 可以维护命令历史实现撤销/重做
- 示例:
java复制public class RemoteControl { private Command command; public void setCommand(Command cmd) { this.command = cmd; } public void pressButton() { command.execute(); } }
-
Receiver(接收者):
- 真正执行操作的对象
- 包含业务逻辑的具体实现
- 示例:
java复制public class Light { public void turnOn() { System.out.println("Light is ON"); } }
3. 实战应用场景剖析
3.1 GUI操作中的典型应用
在Swing开发中,Action接口就是命令模式的体现。我们常这样实现按钮操作:
java复制JButton saveButton = new JButton(new AbstractAction("Save") {
@Override
public void actionPerformed(ActionEvent e) {
// 执行保存操作
document.save();
}
});
这种设计允许:
- 同一操作绑定到不同组件(菜单项+工具栏按钮)
- 方便实现操作状态管理(启用/禁用)
- 支持快捷键绑定
3.2 游戏开发中的输入处理
现代游戏引擎通常使用命令模式处理玩家输入。以下伪代码展示如何解耦输入与操作:
java复制// 定义游戏命令
interface GameCommand {
void execute(Player player);
}
// 具体命令实现
class JumpCommand implements GameCommand {
public void execute(Player player) {
player.jump();
}
}
// 输入映射
Map<KeyCode, GameCommand> keyBindings = new HashMap<>();
keyBindings.put(KeyCode.SPACE, new JumpCommand());
// 游戏循环中处理输入
while (gameRunning) {
KeyCode key = getPressedKey();
GameCommand cmd = keyBindings.get(key);
if (cmd != null) {
cmd.execute(player);
}
}
这种架构的优势:
- 动态重新绑定按键
- 支持录制和回放操作序列
- 方便实现AI控制(AI生成命令对象)
3.3 事务型系统实现
命令模式天然适合需要支持撤销的场景。我们通过维护命令历史栈实现多级撤销:
java复制public class TextEditor {
private StringBuilder text = new StringBuilder();
private Deque<Command> history = new ArrayDeque<>();
public void executeCommand(Command cmd) {
cmd.execute();
history.push(cmd);
}
public void undo() {
if (!history.isEmpty()) {
Command cmd = history.pop();
cmd.undo();
}
}
}
class InsertTextCommand implements Command {
private TextEditor editor;
private String text;
private int position;
// 省略构造方法
public void execute() {
editor.insertText(position, text);
}
public void undo() {
editor.deleteText(position, text.length());
}
}
4. 高级应用技巧
4.1 复合命令模式
通过组合多个命令形成宏命令(Macro Command),实现批处理操作:
java复制public class MacroCommand implements Command {
private List<Command> commands = new Arr
