设计模式之命令模式,以C++为例。
创始人
2024-05-24 16:35:17
0

        命令模式一般叫:command模式,它将请求的发送者和接受者独立开。命令模式的目的是使得请求的发送者与请求的接收者解耦,并且使得请求的发送者可以控制请求的接收者。

目录

一、命令模式能干什么?

二、多级命令

三、进阶写法


一、命令模式能干什么?

        好多时候我们并不明确眼前熟悉事物的重要性以及它呈现在你面前的难能可贵,好像世间本就存在C语言,有C语言就一定有C plus plus,其实不然,这也是我们为什么要知道历史,屈辱的历史可以带来反省,骄傲的历史可以带来自信。

        对于命令模式来讲,刚了解时我并不觉得有什么特殊的地方,只是看到了命令被封装在发送者和接受者之间转换。那么我们就举一个反例,来看看改进成命令模式后有什么进步。

        我们先给出一个简单的智能家居控制代码:

class Light {public:void turnOn() {cout << "Light is on." << endl;}void turnOff() {cout << "Light is off." << endl;}
};class AirConditioner {public:void turnOn() {cout << "Air conditioner is on." << endl;}void turnOff() {cout << "Air conditioner is off." << endl;}
};class RemoteControl {public:void turnOnLight() {light_.turnOn();}void turnOffLight() {light_.turnOff();}void turnOnAirConditioner() {air_conditioner_.turnOn();}void turnOffAirConditioner() {air_conditioner_.turnOff();}private:Light light_;AirConditioner air_conditioner_;
};int main() {RemoteControl remote_control;remote_control.turnOnLight();remote_control.turnOffLight();remote_control.turnOnAirConditioner();remote_control.turnOffAirConditioner();return 0;
}

        这段代码将遥控器和被控制的对象(灯和空调)耦合在一起,导致代码难以维护和扩展。如果想要添加新的设备,就需要在遥控器类中添加新的方法,这样的代码显得非常冗长和不灵活。

类图:

        下面来一段使用命令模式的代码:

class Command {public:virtual ~Command() = default;virtual void execute() = 0;
};class Light {public:void turnOn() {cout << "Light is on." << endl;}void turnOff() {cout << "Light is off." << endl;}
};class AirConditioner {public:void turnOn() {cout << "Air conditioner is on." << endl;}void turnOff() {cout << "Air conditioner is off." << endl;}
};class LightOnCommand : public Command {public:explicit LightOnCommand(Light* light) : light_(light) {}void execute() override {light_->turnOn();}private:Light* light_;
};class LightOffCommand : public Command {public:explicit LightOffCommand(Light* light) : light_(light) {}void execute() override {light_->turnOff();}private:Light* light_;
};class AirConditionerOnCommand : public Command {public:explicit AirConditionerOnCommand(AirConditioner* air_conditioner): air_conditioner_(air_conditioner) {}void execute() override {air_conditioner_->turnOn();}private:AirConditioner* air_conditioner_;
};class AirConditionerOffCommand : public Command {public:explicit AirConditionerOffCommand(AirConditioner* air_conditioner): air_conditioner_(air_conditioner) {}void execute() override {air_conditioner_->turnOff();}private:AirConditioner* air_conditioner_;
};class RemoteControl {public:void setCommand(int slot, Command* on_command, Command* off_command) {on_commands_[slot] = on_command;off_commands_[slot] = off_command;}void onButtonWasPressed(int slot) {on_commands_[slot]->execute();}void offButtonWasPressed(int slot) {off_commands_[slot]->execute();}private:vector on_commands_;vector off_commands_;
};int main() {RemoteControl remote_control;Light light;AirConditioner air_conditioner;LightOnCommand light_on_command(&light);LightOffCommand light_off_command(&light);AirConditionerOnCommand air_conditioner_on_command(&air_conditioner);AirConditionerOffCommand air_conditioner_off_command(&air_conditioner);remote_control.setCommand(0, &light_on_command, &light_off_command);remote_control.setCommand(1, &air_conditioner_on_command,&air__off_command)remote_control.onButtonWasPressed(0);remote_control.offButtonWasPressed(0);remote_control.onButtonWasPressed(1);remote_control.offButtonWasPressed(1);return 0;
}

        通过使用命令模式,你可以在不改变已有代码的前提下,向系统中加入新的命令。增强了代码的可维护性、可读性等。

类图:

二、多级命令

        实现多级命令的方法是在命令类中再次使用命令模式,每一个命令都是另一个命令的容器。

#include 
#include class Command {public:virtual void Execute() = 0;
};class Light {public:void On() {std::cout << "Light is on" << std::endl;}void Off() {std::cout << "Light is off" << std::endl;}
};class LightOnCommand : public Command {public:LightOnCommand(Light& light) : light_(light) {}void Execute() override {light_.On();}private:Light& light_;
};class LightOffCommand : public Command {public:LightOffCommand(Light& light) : light_(light) {}void Execute() override {light_.Off();}private:Light& light_;
};class MacroCommand : public Command {public:MacroCommand(std::vector commands) : commands_(commands) {}void Execute() override {for (auto& command : commands_) {command->Execute();}}private:std::vector commands_;
};int main() {Light light;LightOnCommand light_on_command(light);LightOffCommand light_off_command(light);std::vector macro_commands;macro_commands.push_back(&light_on_command);macro_commands.push_back(&light_off_command);MacroCommand macro_command(macro_commands);macro_command.Execute();return 0;
}

        上面的代码实现了一个简单的多级命令示例,它定义了一个MacroCommand类,用于执行一组命令。

类图:

三、进阶写法

        进阶命令模式包含多级命令、命令队列、命令历史、撤销和重做。

#include 
#include 
#include // 命令基类
class Command {public:virtual void Execute() = 0;virtual void UnExecute() = 0;
};// 具体命令类
class ConcreteCommand : public Command {public:ConcreteCommand(int value) : value_(value) {}void Execute() override {std::cout << "Executing Command with value: " << value_ << std::endl;}void UnExecute() override {std::cout << "Unexecuting Command with value: " << value_ << std::endl;}private:int value_;
};// 多级命令
class CompositeCommand : public Command {public:void AddCommand(Command* command) {commands_.push_back(command);}void Execute() override {for (auto command : commands_) {command->Execute();}}void UnExecute() override {for (auto command : commands_) {command->UnExecute();}}private:std::vector commands_;
};// 命令队列
class CommandQueue {public:void AddCommand(Command* command) {commands_.push_back(command);}void ExecuteCommands() {for (auto command : commands_) {command->Execute();}}void UnExecuteCommands() {for (auto command : commands_) {command->UnExecute();}}private:std::vector commands_;
};// 命令历史
class CommandHistory {public:void PushCommand(Command* command) {commands_.push(command);}Command* PopCommand() {if (commands_.empty()) {return nullptr;}auto command = commands_.top();commands_.pop();return command;}private:std::stack commands_;
};int main() {// 创建命令auto command1 = new ConcreteCommand(1);auto command2 = new ConcreteCommand(2);auto command3 = new ConcreteCommand(3);// 创建多级命令auto composite_command = new CompositeCommand();composite_command->AddCommand(command1);composite_command->AddCommand(command2);// 创建命令队列auto command_queue = new CommandQueue();command_queue->AddCommand(command1);command_queue->AddCommand(command2);command_queue->AddCommand(command3);// 创建命令历史auto command_history = new CommandHistory();command_history->PushCommand(command1);command_history->PushCommand(command2);command_history->PushCommand(command3);// 执行多级命令composite_command->Execute();// 执行命令队列command_queue->ExecuteCommands();// 撤销命令auto command = command_history->PopCommand();if (command) {command->UnExecute();}return 0;
}

类图:

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...