「软件设计模式」命令模式(Command)

news/2025/2/27 5:16:44

揭秘命令模式:用C++实现智能家居的"万能遥控器"

一、从餐厅点餐看命令模式精髓

        想象你坐在餐厅点餐时,服务员记录你的订单交给后厨,这个看似简单的过程蕴含着软件设计的智慧。命令模式(Command)正是将这种"请求封装为对象"的思想应用于软件设计,实现调用者与执行者的完美解耦。

二、命令模式四大核心角色

  1. Command(命令接口)

    • 声明执行操作的接口(execute/undo)
  2. ConcreteCommand(具体命令)

    • 绑定接收者与动作的对应关系
    • 实现execute和undo的具体逻辑
  3. Invoker(调用者)

    • 持有命令对象,触发命令执行
    • 可扩展命令队列、撤销栈等高级功能
  4. Receiver(接收者)

    • 真正执行操作的对象,知道如何实现请求

 

三、C++实战:智能家居控制系统

1.场景描述

开发支持多设备控制的智能家居系统,要求:

  1. 统一控制接口
  2. 支持操作撤销
  3. 方便扩展新设备

 

2.代码实现

#include <iostream>
#include <vector>
#include <memory>
#include <stack>
// 接收者:智能灯
class Light {
public:
    void on() { std::cout << "Light is ON" << std::endl; }
    void off() { std::cout << "Light is OFF" << std::endl; }
};

// 接收者:空调
class AirConditioner {
public:
    void setTemperature(int temp) {
        currentTemp = temp;
        std::cout << "AC set to " << temp << "℃" << std::endl;
    }
    
    int getLastTemp() const { return currentTemp; }
private:
    int currentTemp = 26;
};

// 命令接口
class Command {
public:
    virtual ~Command() = default;
    virtual void execute() = 0;
    virtual void undo() = 0;
};

// 具体命令:开灯命令
class LightOnCommand : public Command {
public:
    explicit LightOnCommand(Light* light) : light(light) {}
    
    void execute() override { light->on(); }
    void undo() override { light->off(); }

private:
    Light* light;
};

// 具体命令:空调温度设置命令
class ACSetCommand : public Command {
public:
    ACSetCommand(AirConditioner* ac, int temp) 
        : ac(ac), newTemp(temp), prevTemp(ac->getLastTemp()) {}
    
    void execute() override { 
        ac->setTemperature(newTemp); 
    }
    
    void undo() override { 
        ac->setTemperature(prevTemp);
    }

private:
    AirConditioner* ac;
    int newTemp;
    int prevTemp;
};

// 调用者:遥控器
class RemoteControl {
public:
    void setCommand(Command* cmd) {
        commands.push_back(cmd);
    }
    
    void pressButton(int slot) {
        if (slot < commands.size()) {
            commands[slot]->execute();
            history.push(commands[slot]);
        }
    }
    
    void undoLast() {
        if (!history.empty()) {
            history.top()->undo();
            history.pop();
        }
    }

private:
    std::vector<Command*> commands;
    std::stack<Command*> history;
};
// main.cc
#include "commond.h"
// 客户端使用示例
int main() {
    // 初始化设备
    Light livingRoomLight;
    AirConditioner bedroomAC;

    // 创建命令对象
    LightOnCommand lightOn(&livingRoomLight);
    ACSetCommand acSet(&bedroomAC, 22);

    // 配置遥控器
    RemoteControl remote;
    remote.setCommand(&lightOn);  // 0号按钮:开灯
    remote.setCommand(&acSet);    // 1号按钮:设置空调

    // 执行命令
    remote.pressButton(0);  // 开灯
    remote.pressButton(1);  // 设置空调温度
    remote.undoLast();       // 撤销空调设置

    return 0;
}

3.执行结果

Light is ON
AC set to 22℃
AC set to 26℃

四、命令模式优势与适用场景

1.核心优势:

  • 彻底解耦调用者与接收者
  • 支持操作队列、日志记录、撤销/重做等扩展
  • 方便实现宏命令(命令组合)

2.典型应用场景:

  1. 需要回调机制的软件系统
  2. 需要实现操作撤销/重做功能
  3. 需要记录操作历史的系统
  4. 需要实现任务调度或延迟执行

五、模式延伸与思考

  1. 命令队列:将命令存入队列实现异步执行
  2. 宏命令:组合多个命令形成复合命令
  3. 事务处理:通过命令日志实现事务回滚
  4. 智能命令:命令对象可自主决定是否执行

思考题:在你的项目中,哪些场景可以用命令模式重构?欢迎在评论区分享你的见解!

        通过本文,我们不仅掌握了命令模式的理论知识,还实现了一个功能完备的智能家居控制系统。这种模式在GUI事件处理、事务系统、工作流引擎等领域都有广泛应用。下次当你需要将"请求"抽象为对象时,不妨试试这个强大的模式。


http://www.niftyadmin.cn/n/5869479.html

相关文章

超大规模分类(四):Partial FC

人脸识别任务里&#xff0c;通常利用全连接层&#xff0c;来做人脸的分类。会面临三个实际问题&#xff1a; 真实的人脸识别数据噪声严重真实的人脸识别数据存在严重的长尾分布问题&#xff0c;一些类别样本多&#xff0c;多数类别样本少人脸类别越来越多&#xff0c;全连接层…

Nacos + Dubbo3 实现微服务的Rpc调用

文章目录 概念整理基本概念概念助记前提RPC与HTTP类比RPC接口类的一些理解 实例代码主体结构父项目公共接口项目提供者项目项目结构POM文件实现配置文件实现公共接口实现程序入口配置启动项目检查是否可以注入到Nacos 消费者项目项目结构POM文件实现配置文件实现注册RPC服务类实…

wordpress按不同页调用不同的标题3种形式

在WordPress中&#xff0c;可以通过多种方式根据不同的页面调用不同的标题。这通常用于实现SEO优化、自定义页面标题或根据页面类型显示不同的标题内容。 使用wp_title函数 wp_title函数用于在HTML的title标签中输出页面标题。你可以通过修改主题的header.php文件来实现自定义…

1.2 Kaggle大白话:Eedi竞赛Transformer框架解决方案02-GPT_4o生成训练集缺失数据

目录 0. 本栏目竞赛汇总表1. 本文主旨2. AI工程架构3. 数据预处理模块3.1 配置数据路径和处理参数3.2 配置API参数3.3 配置输出路径 4. AI并行处理模块4.1 定义LLM客户端类4.2 定义数据处理函数4.3 定义JSON保存函数4.4 定义数据分片函数4.5 定义分片处理函数4.5 定义文件名排序…

第6章 数据工程(二)

6.3 数据治理和建模 数据治理是开展数据价值化活动的基础&#xff0c;关注对数字要素的管控能力覆盖组织对数据相关活动的统筹、评估、指导和监督等工作&#xff0c;需要重点关注元数据、数据标准化、数据质量数据模型和数据建模等方面的内容。 6.3.1 元数据 元数据是关于数…

量子计算可能改变世界的四种方式

世界各地的组织和政府正将数十亿美元投入到量子研究与开发中&#xff0c;谷歌、微软和英特尔等公司都在竞相实现量子霸权。 这其中的利害关系重大&#xff0c;有这么多重要的参与者&#xff0c;量子计算机的问世可能指日可待。 为做好准备&#xff0c;&#xff0c;我们必须了…

Storage Gateway:解锁企业混合云存储的智能钥匙

在数字化转型的浪潮中&#xff0c;企业数据量呈指数级增长&#xff0c;传统本地存储面临成本高、扩展难、管理复杂等挑战。如何实现本地基础设施与云端的无缝协同&#xff0c;构建灵活、安全且经济的存储架构&#xff1f;AWS Storage Gateway 作为混合云存储的核心枢纽&#xf…

健康检查、k8s探针、Grails+Liquibase框架/health 404 Not Found排查及解决

概述 健康检查对于一个pod而言&#xff0c;其重要性不言而喻。 k8s通过探针来实现健康检查。 探针 k8s提供三种探针&#xff1a; 存活探针&#xff1a;livenessProbe就绪探针&#xff1a;readinessProbe启动探针&#xff1a;startupProbe 存活探针 存活探针决定何时重启…