1、介绍
命令模式是⼀种⾏为型设计模式,其允许将请求封装成⼀个对象(命令对象,包含执⾏操作所需的所有信息),并将命令对象按照⼀定的顺序存储在队列中,然后再逐⼀调用执⾏,这些命令也可以⽀持反向操作,进⾏撤销和重做。
命令模式将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
创建步骤:
(1)定义抽象命令类(Command):创建一个抽象类或者接口,其中包含一个纯虚的执行方法,用于执行具体的命令操作。
(2)创建具体命令类(Concrete Command):继承自抽象命令类,实现具体的命令操作,同时持有一个命令接收者对象。
(3)定义命令接收者类(Receiver):这个类包含实际执行命令操作的方法。
(4)创建调用者类(Invoker):这个类负责存储和执行命令对象,可以包含一个命令队列,用于存储多个命令对象。
优点:
(1)降低系统耦合度:将命令的发送者与接收者解耦,方便系统的扩展和维护。
(2)支持命令的撤销和重做:可以灵活地实现对命令的操作历史记录。
(3)增加系统的灵活性:可以方便地添加新的命令。
缺点:
(1)可能导致系统类的数量增加:需要定义多个命令类和相关的处理类。
2、示例
#include <iostream>
#include <vector>
#include <string> // 接收者接口
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 Command {
public:virtual void execute() = 0;
};// 具体命令
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;
}
结果:
Turning on kitchen
Turning on kitchen