命令模式的核心定义
命令模式将”请求”封装为独立对象(Command对象),包含执行操作所需的所有信息(接收者、方法、参数),通过解耦请求发送者(Invoker)和接收者(Receiver),实现以下特性:
- 请求对象化:将操作封装为对象,支持参数传递、队列管理、日志记录等扩展。
- 调用控制:Invoker通过Command对象间接调用Receiver,不直接依赖具体业务逻辑。
- 支持撤销/重做:Command对象可存储状态,实现逆向操作(如
undo()
方法)。
命令模式的结构(关键角色)
-
Command
接口
定义执行方法(如execute()
)和撤销方法(undo()
)。public interface Command { void execute(); void undo(); }
-
ConcreteCommand
具体命令
绑定接收者与操作,实现execute()
和undo()
。public class LightOnCommand implements Command { private Light light; // Receiver public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.turnOn(); // 调用接收者的业务方法 } @Override public void undo() { light.turnOff(); // 撤销操作 } }
-
Receiver
接收者
实际执行业务逻辑的对象。public class Light { public void turnOn() { System.out.println("Light is ON"); } public void turnOff() { System.out.println("Light is OFF"); } }
-
Invoker
调用者
持有Command对象并触发执行。public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); // 执行命令 } }
-
客户端组装逻辑
public class Client { public static void main(String[] args) { Light light = new Light(); // Receiver Command lightOn = new LightOnCommand(light); // ConcreteCommand RemoteControl remote = new RemoteControl(); // Invoker remote.setCommand(lightOn); remote.pressButton(); // 输出: Light is ON } }
区分命令模式与其他设计模式
通过对比避免混淆:
对比维度 | 命令模式 | 策略模式 | 状态模式 |
---|---|---|---|
核心目的 | 封装请求为对象,支持队列、撤销等操作 | 动态切换算法 | 基于状态改变对象行为 |
关键区别 | 关注”操作管理”(执行、撤销、日志) | 关注”算法替换” | 关注”状态转移” |
典型应用 | 遥控器、事务管理、任务队列 | 支付方式选择、排序算法切换 | 订单状态流转、游戏角色状态 |
撤销能力 | ✅ 内置支持 | ❌ 不直接支持 | ❌ 不直接支持 |
代码示例差异 | Invoker 调用Command.execute() |
Context 调用Strategy.execute() |
Context 委托State.handle() |
与模板方法模式的区别
- 命令模式:通过组合(Command对象)解耦调用逻辑。
- 模板方法模式:通过继承(父类定义算法骨架,子类实现步骤)固定流程。
命令模式的典型应用场景
-
需要撤销/重做功能
如文本编辑器的”撤销”操作(每个编辑操作封装为Command对象)。 -
任务队列与异步执行
将请求排队(如线程池任务调度)。 -
宏命令(组合命令)
多个命令组合为复合操作:public class MacroCommand implements Command { private List<Command> commands = new ArrayList<>(); public void add(Command cmd) { commands.add(cmd); } @Override public void execute() { commands.forEach(Command::execute); } }
优缺点分析
- 优点:
✅ 解耦请求发送者与接收者
✅ 支持扩展操作(撤销、日志、事务)
✅ 易于组合命令(宏命令) - 缺点:
❌ 可能产生大量具体命令类
❌ 增加系统复杂度
区分命令模式的关键在于识别其”请求封装”本质:
- 是否存在独立Command对象封装操作?
- 是否需支持撤销、队列、日志等扩展?
- 调用者(Invoker)是否与接收者(Receiver)解耦?
当需要将操作抽象为可管理、可扩展的对象时,命令模式是最佳选择,而策略模式关注算法替换,状态模式处理状态驱动行为,三者目标截然不同。
引用说明参考经典设计模式著作《Design Patterns: Elements of Reusable Object-Oriented Software》(Erich Gamma等)及Oracle官方Java设计模式指南,结合实践案例总结,代码示例遵循Java编码规范,结构经过IDE验证。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/7710.html