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

命令模式

  • 概念
  • 创建步骤
  • 示例
    • 示例一
      • 代码实现
      • 运行结果
    • 示例二
      • 代码实现
      • 运行结果
    • 示例三
      • 示例代码
      • 运行结果
    • 示例四
      • 代码实现
      • 运行结果
  • 应用场景

概念

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

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

创建步骤

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

1.定义抽象命令类(Command):创建一个抽象类或者接口,其中包含一个纯虚的执行方法,用于执行具体的命令操作。
2.创建具体命令类(Concrete Command):继承自抽象命令类,实现具体的命令操作,同时持有一个命令接收者对象。
3.定义命令接收者类(Receiver):这个类包含实际执行命令操作的方法。
4.创建调用者类(Invoker):这个类负责存储和执行命令对象,可以包含一个命令队列,用于存储多个命令对象。

示例

示例一

代码实现

#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;
}

运行结果

在这里插入图片描述

示例二

代码实现

#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;
}

运行结果

在这里插入图片描述

示例三

示例代码

#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;
}

运行结果

在这里插入图片描述

示例四

代码实现

#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.当系统需要执行一组操作时:命令模式可以定义宏命令来实现该功能。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/284669.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL主从复制详解

目录 1. 主从复制的工作原理 1.1. 主从复制的角色 1.2. 主从复制的流程 2. 配置MySQL主从复制 2.1. 确保主服务器开启二进制日志 2.2. 设置从服务器 2.3. 连接主从服务器 2.4. 启动复制 3. 主从复制的优化与注意事项 3.1. 优化复制性能 3.2. 注意复制延迟 3.3. 处理…

Ubuntu 常用命令之 cat 命令用法介绍

cat是一个常用的命令行工具&#xff0c;它用于连接和显示文件的内容。cat这个名字来源于它的功能 - concatenate(连接)。 以下是cat命令的一些基本用法 &#x1f447;显示文件内容&#xff1a;cat后面跟上文件名&#xff0c;就可以在终端显示出文件的内容。例如&#xff0c;c…

web应用开发技术的一些概念

一、Servlet 1.Servlet的工作过程&#xff1a; Servelt的工作流程示意图 &#xff08;1&#xff09;客户端发起一个Http请求到服务器&#xff0c;请求特定的资源或者是要执行特定的操作 &#xff08;2&#xff09;服务器在接收到请求后&#xff0c;根据请求相应的URL将请求分发…

制造企业MES管理系统可以和AI结合应用吗

在当今的数字化时代&#xff0c;人工智能AI和MES生产管理系统的结合将成为制造企业发展的重要趋势。这种结合可以为制造企业带来许多优势&#xff0c;如提高生产效率、降低成本、优化资源利用等。本文将探讨MES管理系统和AI的结合以及它们在制造企业中的应用&#xff0c;并分析…

从零开始实现分布式服务系统

文章目录 开发前言分布式模型系统图解注册中心模块基础服务模块被依赖的服务模块&#xff08;日志服务&#xff09;服务模块&#xff08;访问服务&#xff09;运行效果开发总结 开发前言 分布式系统具有高可靠性、高性能、可扩展性、灵活性、数据共享、可靠性和地理分布等优点…

一款开源免费美观的WinForm UI控件库 - ReaLTaiizor

前言 今天推荐一款基于MIT license开源、免费、美观的.NET WinForm UI控件库&#xff1a;ReaLTaiizor。 什么是WinForm&#xff1f; WinForm是一个传统的桌面应用程序框架&#xff0c;它基于 Windows 操作系统的原生控件和窗体。通过简单易用的 API&#xff0c;开发者可以快速…

pycharm通过ssh连接远程服务器的docker容器进行运行和调试代码

pycharm连接远程服务器的docker容器通常有两种方法&#xff1a; 第一种&#xff1a;pycharm通过ssh连接已在运行中的docker容器 第二种&#xff1a;pycharm连接docker镜像&#xff0c;pycharm运行代码再自动创建容器 第一种方法比较通用简单&#xff0c;作者比较推崇。 条件…

频谱论文:基于张量Tucker分解的频谱地图构建算法

#频谱# [1]陈智博,胡景明,张邦宁 郭道省.(2023).基于张量Tucker分解的频谱地图构建算法.电子与信息学报(11),4161-4169. &#xff08;陆军工程大学&#xff09; 研究内容 将动态电磁环境的时变频谱地图建模为3维频谱张量&#xff0c;通过张量Tucker分解提取出具有物理意义的核…

Vue 自定义搜索输入框SearchInput

效果如下&#xff1a; 组件代码 <template><div class"search-input flex flex-space-between flex-center-cz"><input type"text" v-model"value" :ref"inpuName" :placeholder"placeholder" keyup.enter&…

双向链表原来是这样实现的!

文章目录 前言1. 双向链表的结构2. 双链表的定义和结构3. 定义结构体(ListNode)2.创建返回链表的头结点CreateList函数实现: 3.初始化双向链表ListCreate定义函数&#xff1a;实现函数&#xff1a; 4. 双向链表打印(ListPrint)定义函数&#xff1a;实现函数&#xff1a; 5. 尾插…

Python---多任务的介绍

1. 提问 利用现学知识能够让两个函数或者方法同时执行吗? 不能&#xff0c;因为之前所写的程序都是单任务的&#xff0c;也就是说一个函数或者方法执行完成另外一个函数或者方法才能执行&#xff0c;要想实现这种操作就需要使用多任务。 多任务的最大好处是充分利用CPU资源&…

算法学习——栈与队列

栈与队列 栈与队列理论基础用栈实现队列思路代码 用队列实现栈思路代码 删除字符串中的所有相邻重复项思路代码 有效的括号思路代码 逆波兰表达式求值思路代码 滑动窗口最大值思路代码未完待续 前 K 个高频元素思路代码拓展 总结栈在系统中的应用括号匹配问题字符串去重问题逆波…