命令模式通过封装请求为对象实现调用者与接收者解耦,核心是抽象Command接口及具体命令类,由Invoker统一管理执行、撤销与扩展。

命令模式在C++中通过将请求封装为对象,实现请求发起者与执行者的解耦。核心是定义统一的命令接口,让调用者无需知道具体操作细节,只管“发号施令”。
定义命令接口和具体命令类
所有命令都继承自抽象基类 Command,它声明一个 execute() 方法。每个具体命令(如打开文件、保存文件)实现该方法,并持有对应接收者(Receiver)的引用或指针。
例如:
-
Receiver 可以是
Document类,提供open()、save()等实际操作; -
OpenCommand 构造时接收一个
Document*,execute()中调用其open(); -
SaveCommand 同理,调用
save()。
引入调用者(Invoker)管理命令
Invoker 不直接操作 Receiver,而是持有一个或多个 Command*。它提供 setCommand() 和 executeCommand() 接口。支持按钮、快捷键、宏录制等场景——同一 Invoker 可切换不同命令。
立即学习“C++免费学习笔记(深入)”;
常见做法:
- 用
std::unique_ptr管理命令生命周期; - 支持撤销时,命令需增加
undo()方法,并在 Invoker 中保存历史命令栈; - 可扩展为支持队列式执行(如批处理命令)。
使用示例:简易文本编辑器操作
假设用户点击“保存”按钮:
- UI 层创建
SaveCommand{&doc}; - 传给
menuBar.setCommand(std::move(cmd)); - 用户点击时,
menuBar.executeCommand()调用命令的execute(),最终触发doc.save()。
整个过程不暴露 Document 细节,菜单、工具栏、快捷键均可复用同一套命令对象。
关键细节与建议
命令对象应尽量轻量,避免在构造时执行耗时操作;状态(如目标文件路径)应在构造或 execute() 前设置好。
- 用
std::function+ lambda 可快速实现一次性命令,适合简单场景; - 若需撤销/重做,命令须保存必要上下文(如修改前文本、光标位置),并确保
undo()安全可逆; - 避免命令持有裸指针导致悬挂,优先用弱引用或观察者模式配合生命周期管理。
基本上就这些。命令模式不复杂但容易忽略命令对象的生命周期和状态一致性。











