C++设计模式之——命令模式

命令模式

概念

命令模式是一种行为型设计模式,它允许将请求封装为一个对象,从而使得可以参数化客户端请求、将请求排队或者记录请求日志,以及支持可撤销的操作。

在C++中,命令模式通常由一个抽象命令类、具体命令类、命令接收者类和调用者类组成。

创建步骤

命令模式的主要步骤包括:

1.定义抽象命令类(Command):创建一个抽象类或者接口,其中包含一个纯虚的执行方法,用于执行具体的命令操作。

2.创建具体命令类(Concrete Command):继承自抽象命令类,实现具体的命令操作,同时持有一个命令接收者对象。

3.定义命令接收者类(Receiver):这个类包含实际执行命令操作的方法。

4.创建调用者类(Invoker):这个类负责存储和执行命令对象,可以包含一个命令队列,用于存储多个命令对象。

示例

示例一

代码实现

cpp 复制代码
#include <iostream>  
#include <vector>  
#include <string>  

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

// 接收者接口  
class Receiver {//子类必须重写抽象类中所有的纯虚函数,否则子类也是抽象类
public:
    virtual void turnOn(std::string light) = 0;
    virtual void setSpeed(int speed) = 0;
};

// 具体接收者  
class LightReceiver : public Receiver {
public:
    void turnOn(std::string light) override {//只重写抽象类中的turnOn函数,LightReceiver也会变为抽象类
        std::cout << "Turning on " << light << std::endl;
    }
    void setSpeed(int speed) override {
        std::cout << "Setting fan speed to " << speed << std::endl;
    }
};

// 具体接收者  
class Fan : public Receiver {
public:
    void turnOn(std::string light) override {
        std::cout << "Turning on " << light << std::endl;
    }
    void setSpeed(int speed) override {
        std::cout << "Setting fan speed to " << speed << std::endl;
    }
};

// 具体命令  
class LightCommand : public Command {
public:
    LightCommand(LightReceiver*pLight,std::string light) : m_pLight(pLight),light_(light) {}
    void execute() override {
        std::cout << "Turning on " << light_ << std::endl;
        m_pLight->turnOn(light_);
    }
private:
    std::string light_;
    LightReceiver* m_pLight;
};

// 具体命令  
class FanCommand : public Command {
public:
    FanCommand(Fan* pFan,int speed) : m_pFan(pFan),speed_(speed) {}
    void execute() override {
        std::cout << "Setting fan speed to " << speed_ << std::endl;
        m_pFan->setSpeed(speed_);
    }
private:
    int speed_;
    Fan* m_pFan;
};

// 调用者接口  
class Invoker {
public:
    virtual void setCommand(Command* command) = 0;
    virtual void execute() = 0;
};

// 具体调用者  
class LightInvoker : public Invoker {
public:
    void setCommand(Command* command) override { m_pCommand = command; }
    void execute() override { m_pCommand->execute(); }
private:
    Command* m_pCommand;
};

int main() {
    LightReceiver light;
    LightCommand lightCommand(&light,"kitchen");
    LightInvoker lightInvoker;
    lightInvoker.setCommand(&lightCommand);
    lightInvoker.execute(); // 执行命令,调用接收者的turnOn方法,输出"Turning on kitchen"  
    return 0;
}

运行结果

示例二

代码实现

cpp 复制代码
#include <iostream>  
#include <vector>  
#include <string>  

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

// 具体命令 - 加法命令  
class AddCommand : public Command {
public:
    AddCommand(int a, int b) : a_(a), b_(b) {}
    void execute() override {
        std::cout << "Result: " << a_ + b_ << std::endl;
    }
private:
    int a_, b_;
};

// 具体命令 - 减法命令  
class SubtractCommand : public Command {
public:
    SubtractCommand(int a, int b) : a_(a), b_(b) {}
    void execute() override {
        std::cout << "Result: " << a_ - b_ << std::endl;
    }
private:
    int a_, b_;
};

// 调用者 - 计算器  
class Calculator {
public:
    void addCommand(Command* command) {
        commands_.push_back(command);
    }
    void executeCommands() {
        for (auto command : commands_) {
            command->execute();
        }
    }
    ~Calculator() 
    {
        for (const auto &command: commands_)
        {
            delete command;
        }
    }
private:
    std::vector<Command*> commands_;
};

int main() {
    Calculator calculator;
    calculator.addCommand(new AddCommand(5, 3)); // 添加加法命令,执行后输出"Result: 8"  
    calculator.addCommand(new SubtractCommand(10, 4)); // 添加减法命令,执行后输出"Result: 6"  
    calculator.executeCommands(); // 执行所有命令,依次输出"Result: 8"和"Result: 6"  
    return 0;
}

运行结果

示例三

示例代码

cpp 复制代码
#include <iostream>
#include <vector>

// 抽象命令类
class Command {
public:
    virtual void execute() = 0;
};

// 命令接收者类
class Receiver {
public:
    void action() {
        std::cout << "Receiver action" << std::endl;
    }
};

// 具体命令类
class ConcreteCommand : public Command {
private:
    Receiver* receiver;

public:
    ConcreteCommand(Receiver* recv) : receiver(recv) {}

    void execute() {
        receiver->action();
    }
};


// 调用者类
class Invoker {
private:
    std::vector<Command*> commands;

public:
    void addCommand(Command* cmd) {
        commands.push_back(cmd);
    }

    void executeCommands() {
        for (Command* cmd : commands) {
            cmd->execute();
        }
    }
};

int main() {
    Receiver* receiver = new Receiver();
    ConcreteCommand* cmd = new ConcreteCommand(receiver);

    Invoker invoker;
    invoker.addCommand(cmd);
    invoker.executeCommands();

    delete receiver;
    delete cmd;

    return 0;
}

运行结果

示例四

代码实现

cpp 复制代码
#include <iostream>
#include <vector>

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

// 具体命令类 - 打开电视
class TurnOnTVCommand : public Command {
public:
    void execute() {
        std::cout << "Turning on the TV" << std::endl;
    }
};

// 具体命令类 - 关闭电视
class TurnOffTVCommand : public Command {
public:
    void execute() {
        std::cout << "Turning off the TV" << std::endl;
    }
};

// 遥控器
class RemoteControl {
private:
    Command* command;

public:
    void setCommand(Command* cmd) {
        command = cmd;
    }

    void pressButton() {
        command->execute();
    }
};

int main() {
    RemoteControl remote;

    TurnOnTVCommand onCommand;
    TurnOffTVCommand offCommand;

    remote.setCommand(&onCommand);
    remote.pressButton();

    remote.setCommand(&offCommand);
    remote.pressButton();

    return 0;
}

运行结果

应用场景

1.实现宏命令:命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。

2.日志记录和事务处理:在命令模式中,可以方便地增加额外功能,比如日志记录。此外,如果一个操作需要由多个子操作构成,而这些子操作需要被打包在一起作为一个单独的事务来执行,命令模式可以帮助实现这一功能。

3.支持撤销和重做:命令模式可以方便地实现撤销(Undo)和重做(Redo)功能。

4.队列请求:当需要将请求排队,例如用户界面中的点击事件或网络请求,命令模式可以将这些请求封装为对象并放入队列中等待处理。

5.多线程操作:命令模式可以帮助多线程操作,多个线程可以发出操作命令,程序可以在后台自动发出指令并处理其他业务,而不用等待线程完成操作。

6.系统需要将请求调用者和请求接收者解耦:命令模式使调用者和接收者不直接交互。

7.系统随机请求命令或经常增加、删除命令:命令模式可以方便地实现这些功能。

8.当系统需要执行一组操作时:命令模式可以定义宏命令来实现该功能。

总的来说,命令模式的应用场景主要在于解耦请求与实现,封装接收方具体命令的实现细节,使得请求方的代码架构稳定,具备良好的扩展性。

相关推荐
家有狸花1 小时前
VSCODE驯服日记(三):配置C++环境
c++·ide·vscode
dengqingrui1232 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝2 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O2 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
ok!ko3 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
拉里小猪的迷弟4 小时前
设计模式-创建型-常用:单例模式、工厂模式、建造者模式
单例模式·设计模式·建造者模式·工厂模式
小飞猪Jay5 小时前
C++面试速通宝典——13
jvm·c++·面试
rjszcb6 小时前
一文说完c++全部基础知识,IO流(二)
c++
严文文-Chris6 小时前
【设计模式-中介者模式】
设计模式·中介者模式
刷帅耍帅6 小时前
设计模式-中介者模式
设计模式·中介者模式