设计模式 Day 9:命令模式(Command Pattern)完整讲解与实战应用

🔄 回顾 Day 8:策略模式

在 Day 8 中我们讲解了策略模式:

  • 用于封装多个可切换的算法逻辑,让调用者在运行时选择合适的策略。
  • 它强调的是"行为选择",是针对"算法或行为差异"而设计。
  • 通过 PaymentStrategy、路径规划等实战场景,我们实现了灵活扩展与开闭分离。

而今天的命令模式,虽然也封装行为,但它的核心在于:

将"请求"与"执行"彻底解耦,支持操作排队、记录、撤销、重做等高级控制。


一、什么是命令模式?

命令模式(Command Pattern)是行为型设计模式的一种,它将"请求封装为对象",从而让你可以:

  • 将请求排队
  • 将请求记录日志
  • 支持命令撤销、重做
  • 实现请求者与执行者的解耦

二、适用场景

场景 描述
撤销/重做操作 图形编辑器、文字编辑器需要保存执行历史
请求排队 打印任务、网络任务、远程执行命令
按钮映射 将按钮点击操作映射为命令对象
宏命令/脚本系统 一组命令批量执行

三、命令模式结构(UML)

复制代码
+----------------+       +-----------------+       +---------------+
|   Client       |-----> |   Invoker       |-----> |   Command     |
+----------------+       +-----------------+       +---------------+
                                               /\
                                              /
                           +-----------------------+
                           | ConcreteCommand       |
                           +-----------------------+
                           | +execute()            |
                           +-----------------------+
                                   |
                                   v
                           +--------------------+
                           | Receiver (执行者)  |
                           +--------------------+
                           | +action()          |
                           +--------------------+

✅ 角色解析:

角色 职责
Command 抽象命令接口,定义执行方法
ConcreteCommand 实现命令接口,调用 Receiver 执行命令
Receiver 命令的实际执行者
Invoker 触发命令的角色,如按钮、菜单项
Client 负责构建命令对象,并设定 Invoker 的命令

四、C++ 实现:遥控器控制多个家电

✅ 抽象命令类

cpp 复制代码
class Command {
public:
    virtual void execute() = 0;
    virtual ~Command() = default;
};

✅ 接收者类(家电)

cpp 复制代码
class Light {
public:
    void on() { std::cout << "灯打开了\n"; }
    void off() { std::cout << "灯关闭了\n"; }
};

class Fan {
public:
    void start() { std::cout << "风扇启动了\n"; }
    void stop() { std::cout << "风扇关闭了\n"; }
};

✅ 具体命令类

cpp 复制代码
class LightOnCommand : public Command {
    Light* light;
public:
    LightOnCommand(Light* l) : light(l) {}
    void execute() override { light->on(); }
};

class FanStartCommand : public Command {
    Fan* fan;
public:
    FanStartCommand(Fan* f) : fan(f) {}
    void execute() override { fan->start(); }
};

✅ 调用者类(遥控器)

cpp 复制代码
class RemoteControl {
    std::map<std::string, std::unique_ptr<Command>> slots;
public:
    void setCommand(const std::string& key, std::unique_ptr<Command> cmd) {
        slots[key] = std::move(cmd);
    }
    void pressButton(const std::string& key) {
        if (slots.count(key)) slots[key]->execute();
        else std::cout << "无效按钮" << std::endl;
    }
};

✅ 使用示例

cpp 复制代码
int main() {
    Light light;
    Fan fan;
    RemoteControl remote;

    remote.setCommand("light_on", std::make_unique<LightOnCommand>(&light));
    remote.setCommand("fan_start", std::make_unique<FanStartCommand>(&fan));

    remote.pressButton("light_on");
    remote.pressButton("fan_start");
    return 0;
}

五、进阶:支持撤销与命令队列

✅ 撤销接口扩展:

cpp 复制代码
class Command {
public:
    virtual void execute() = 0;
    virtual void undo() = 0;
    virtual ~Command() = default;
};

具体命令实现 undo:记录之前状态并逆操作。

✅ 命令队列:

cpp 复制代码
std::queue<std::unique_ptr<Command>> commandQueue;
commandQueue.push(...);
while (!commandQueue.empty()) {
    commandQueue.front()->execute();
    commandQueue.pop();
}

六、命令模式与其他模式对比

模式 区别焦点
策略模式 封装"算法",客户端主动调用
命令模式 封装"请求",支持请求与执行解耦
观察者模式 事件驱动响应,多观察者监听

七、面试回答模板

"命令模式我们在设备控制系统中使用得较多,例如遥控器设置不同按键指令时,通过封装命令类(Command),将操作与实际执行者解耦,便于我们记录命令、支持批量执行、撤销重做等功能。同时,Invoker(遥控器)只需要触发,不关心具体如何执行,实现了请求分发中心的架构。"


八、记忆口诀

"请求包起来,请求再排队;触发和执行,隔离不耦合。"


九、明日预告:Day 10

模板方法模式(Template Method):定义算法骨架,延迟具体实现给子类,实现复用与规范统一。

相关推荐
博风16 分钟前
17、设计模式应用举例:单件模式:多线程争冠军
设计模式
高晶13 小时前
无乘法器实现LC二阶滤波器:基于移位运算的快速算法与四种精度推导
算法·设计模式·程序员
高晶13 小时前
主从自动分配算法:平均值乘以设备数一半的选举基准值解析
算法·设计模式·程序员
延晗13 小时前
【从零开始 DeepSeek Harness 插件开发教程】二、一切皆插件:简单理解一下 Cordis 内核与 DSH 心智模型
设计模式·deepseek
高晶14 小时前
Android 通讯录应用开发实战:从零搭建 SQLite 数据持久化完整项目
android·设计模式·前端框架
日和雫20 小时前
封装、继承、多态 & 组合,为什么组合大于继承?
设计模式
代钦塔拉1 天前
【C++/Qt 进阶】设计模式系列(6):桥接模式——把“两个独立变化的维度“拆开
c++·qt·设计模式
haluhalu.1 天前
深入理解AIAgent(1.3)--- 设计模式
人工智能·python·设计模式·langchain
高晶2 天前
CANopen 在 BMS 系统中的 C 语言实战指南
设计模式·程序员
博风2 天前
13、设计模式应用举例:工厂方法模式:创建药品对象
设计模式·工厂方法模式