当前位置: 首页 > article >正文

c++命令模式

一.概念

命令模式(Command Pattern)是一种行为设计模式,它将请求封装为对象,从而使您可以使用不同的请求、队列或日志请求,以及支持可撤销操作。命令模式的主要组成部分包括:

  1. 命令接口(Command Interface):定义一个执行操作的接口。
  2. 具体命令(Concrete Command):实现命令接口,定义与接收者之间的绑定关系。
  3. 接收者(Receiver):知道如何实施与执行相关的操作。
  4. 调用者(Invoker):要求该命令执行请求。
  5. 客户端(Client):创建一个具体命令对象并设置其接收者。

下面是一个简单的 C++ 示例,展示了命令模式的实现:

#include <iostream>  
#include <vector>  
#include <memory>  

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

// 接收者  
class Light {  
public:  
    void turnOn() {  
        std::cout << "Light is ON" << std::endl;  
    }  
    void turnOff() {  
        std::cout << "Light is OFF" << std::endl;  
    }  
};  

// 具体命令  
class TurnOnCommand : public Command {  
private:  
    Light& light;  
public:  
    TurnOnCommand(Light& l) : light(l) {}  
    void execute() override {  
        light.turnOn();  
    }  
};  

class TurnOffCommand : public Command {  
private:  
    Light& light;  
public:  
    TurnOffCommand(Light& l) : light(l) {}  
    void execute() override {  
        light.turnOff();  
    }  
};  

// 调用者  
class RemoteControl {  
private:  
    std::unique_ptr<Command> command;  
public:  
    void setCommand(std::unique_ptr<Command> cmd) {  
        command = std::move(cmd);  
    }  
    void pressButton() {  
        if (command) {  
            command->execute();  
        }  
    }  
};  

// 客户端  
int main() {  
    Light livingRoomLight;  

    TurnOnCommand turnOn(livingRoomLight);  
    TurnOffCommand turnOff(livingRoomLight);  

    RemoteControl remote;  

    // 打开灯  
    remote.setCommand(std::make_unique<TurnOnCommand>(livingRoomLight));  
    remote.pressButton();  

    // 关闭灯  
    remote.setCommand(std::make_unique<TurnOffCommand>(livingRoomLight));  
    remote.pressButton();  

    return 0;  
}  

代码分析:

  1. 命令接口:Command 定义了一个 execute 方法,所有具体命令都需要实现这个方法。
  2. 接收者:Light 类有两个方法 turnOn 和 turnOff,用于控制灯的状态。
  3. 具体命令:TurnOnCommand 和 TurnOffCommand 类实现了 Command 接口,并持有一个 Light 对象的引用,以便在执行时调用相应的方法。
  4. 调用者:RemoteControl 类持有一个命令对象,并在 pressButton 方法中调用该命令的 execute 方法。
  5. 客户端:在 main 函数中,创建了 Light 对象和命令对象,并通过 RemoteControl 来执行命令。

这种模式的优点是可以将请求的发送者和接收者解耦,支持命令的撤销和重做等功能。

二.案例分析

1. 工厂类

class DeviceFactory {
public:
    static DeviceFactory& instance() {
        static DeviceFactory instance;
        return instance;
    }

    //这里写的太死了,看命令模式
    Device* createDevice(const DeviceConfig& config) {
        if (config.type() == "万用表") {
            return new MultimeterDevice(QUuid::createUuid().toString(), config);
        } else if (config.type() == "示波器") {
            return new Oscilloscope(QUuid::createUuid().toString(), config);
        }
        return nullptr;
    }

private:
    DeviceFactory() = default;
    DeviceFactory(const DeviceFactory&) = delete;
    DeviceFactory& operator=(const DeviceFactory&) = delete;
};
  • 目前存在的问题:假如我以后要添加新的设备,这个工厂就不在适用了,所以这个工厂并不是一个好的架构。

2. 工厂类优化(命令模式)

为了使 DeviceFactory 更加灵活并支持新的设备类型而不需要修改现有代码,可以使用命令模式和注册机制。通过将设备的创建逻辑从工厂中分离出来,并使用一个注册表来管理设备类型及其对应的创建命令,可以实现更好的扩展性。

实现步骤

  1. 定义设备接口:创建一个设备接口,所有设备都需要实现这个接口。
  2. 创建命令接口:定义一个命令接口,用于创建设备。
  3. 实现具体命令:为每种设备类型实现具体的命令类。
  4. 注册机制:使用一个注册表来管理设备类型和对应的命令类。
  5. 修改工厂:在工厂中查找注册表并调用相应的命令类。

代码示例

以下是使用命令模式和注册机制的示例代码:

#include <iostream>  
#include <memory>  
#include <unordered_map>  
#include <functional>  
#include <QString>  
#include <QUuid>  

// 设备接口  
class Device {  
public:  
    virtual void operate() = 0;  
    virtual ~Device() = default;  
};  

// 具体设备类  
class MultimeterDevice : public Device {  
public:  
    MultimeterDevice(const QString& id, const DeviceConfig& config) {  
        // 初始化万用表  
    }  
    void operate() override {  
        std::cout << "Operating Multimeter" << std::endl;  
    }  
};  

class Oscilloscope : public Device {  
public:  
    Oscilloscope(const QString& id, const DeviceConfig& config) {  
        // 初始化示波器  
    }  
    void operate() override {  
        std::cout << "Operating Oscilloscope" << std::endl;  
    }  
};  

// 设备创建命令接口  
class DeviceCommand {  
public:  
    virtual Device* create(const DeviceConfig& config) = 0;  
    virtual ~DeviceCommand() = default;  
};  

// 具体命令类  
class MultimeterCommand : public DeviceCommand {  
public:  
    Device* create(const DeviceConfig& config) override {  
        return new MultimeterDevice(QUuid::createUuid().toString(), config);  
    }  
};  

class OscilloscopeCommand : public DeviceCommand {  
public:  
    Device* create(const DeviceConfig& config) override {  
        return new Oscilloscope(QUuid::createUuid().toString(), config);  
    }  
};  

// 工厂类  
class DeviceFactory {  
public:  
    static DeviceFactory& instance() {  
        static DeviceFactory instance;  
        return instance;  
    }  

    void registerDevice(const QString& type, std::unique_ptr<DeviceCommand> command) {  
        commands[type] = std::move(command);  
    }  

    Device* createDevice(const DeviceConfig& config) {  
        auto it = commands.find(config.type());  
        if (it != commands.end()) {  
            return it->second->create(config);  
        }  
        return nullptr;  
    }  

private:  
    DeviceFactory() = default;  
    DeviceFactory(const DeviceFactory&) = delete;  
    DeviceFactory& operator=(const DeviceFactory&) = delete;  

    std::unordered_map<QString, std::unique_ptr<DeviceCommand>> commands;  
};  

// 客户端代码  
int main() {  
    DeviceFactory& factory = DeviceFactory::instance();  

    // 注册设备类型  
    factory.registerDevice("万用表", std::make_unique<MultimeterCommand>());  
    factory.registerDevice("示波器", std::make_unique<OscilloscopeCommand>());  

    DeviceConfig config1; // 假设已设置为万用表配置  
    Device* device1 = factory.createDevice(config1);  
    if (device1) {  
        device1->operate();  
        delete device1; // 记得释放内存  
    }  

    DeviceConfig config2; // 假设已设置为示波器配置  
    Device* device2 = factory.createDevice(config2);  
    if (device2) {  
        device2->operate();  
        delete device2; // 记得释放内存  
    }  

    return 0;  
}  

代码分析:

  1. 设备接口和具体设备:Device 接口定义了设备的基本操作,MultimeterDevice 和 Oscilloscope 是具体的设备实现。
  2. 命令接口和具体命令:DeviceCommand 接口定义了创建设备的方法,具体命令类如 MultimeterCommand 和 OscilloscopeCommand 实现了该接口。
  3. 工厂类:DeviceFactory 维护一个命令注册表,使用 registerDevice 方法注册设备类型和对应的命令类。在 createDevice 方法中,根据设备类型查找并调用相应的命令类创建设备。
  4. 客户端代码:在客户端中,首先注册设备类型,然后创建设备并执行操作。

优点:

  • 扩展性:添加新设备只需实现新的命令类并在工厂中注册,而无需修改现有代码。
  • 解耦:设备创建逻辑与工厂分离,便于维护和测试。

http://www.kler.cn/news/285236.html

相关文章:

  • Vscode推送代码到 Gitee
  • 关于一个早期的计算机网络的理解
  • Nginx 负载均衡深入指南:`proxy_pass` 指令的高效使用
  • Nginx: 负载均衡场景下上游服务器异常时的容错机制
  • docker python 3.11 容器报错
  • Windows连接虚拟机中的mysql5失败
  • C程序设计(潭浩强教授版)精选程序题
  • Bluetooth: gatt profile
  • 学习之SQL语句之DCL(数据控制语言)
  • 广电手机卡靠谱吗?
  • 【爬虫软件】YouTube评论采集工具
  • LVS工作模式
  • IBM退出中国,LabVIEW未来走向何方?
  • 5G智慧工地项目汇报方案
  • ElementPlus下拉框实现可选择,可输入
  • pm2 + linux + nginx
  • C++拷贝构造函数
  • 智能儿童对讲机语音交互,乐鑫ESP-RTC音视频通信,ESP32无线语音方案
  • JAVA:文字写入图片、图片插入图片
  • 睿考网:2024年中级经济师考试备考技巧
  • Java设计模式【享元模式】-结构型
  • mac在终端中使用vscode打开文件或者文件夹
  • PowerShell脚本编写:自动化Windows开发工作流程
  • audiocraft - 免费文本转音乐、AI音乐生成、AI音乐创作工具,Facebook开源,本地一键整合包下载
  • Redisson 实现分布式锁
  • 类和对象(4)
  • zabbix对接Grafana
  • Linux的远程登录教程(超详细)
  • 排序算法之桶排序详细解读(附带Java代码解读)
  • 模型 错位竞争(战略规划)