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.mzph.cn/news/232945.shtml

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

相关文章

libp2p 快速开始

文章目录 第一部分&#xff1a;libp2p 快速入门一、什么是libp2plibp2p 发展历程libp2p的特性p2p 网络和我们熟悉的 client/server 网络的区别&#xff1a; 二、Libp2p的实现目标三、Libp2p的用途四、运行 Libp2p 协议流程libp2p 分为三层libp2p 还有一个局域网节点发现协议 mD…

原生JS实现组件切换(不刷新页面)

这是通过原生Es6实现的组件切换&#xff0c;代码很简单&#xff0c;原理和各种框架原理大致相同。 创建文件 ├── component&#xff1a;存放组件 │ ├── home1.js&#xff1a;组件1 │ ├── home2.js&#xff1a;组件2 ├── index.html ├── index.js初始化ht…

LLaMA系列模型

1.LLama 1.1 简介 Open and Efficient Foundation Language Models (Open但没完全Open的LLaMA) 2023年2月&#xff0c;Meta&#xff08;原Facebook&#xff09;推出了LLaMA大模型&#xff0c;使用了1.4T token进行训练&#xff0c;虽然最大模型只有65B&#xff0c;但在相关评…

[23] GaussianAvatars: Photorealistic Head Avatars with Rigged 3D Gaussians

[paper | proj] 给定FLAME&#xff0c;基于每个三角面片中心初始化一个3D Gaussian&#xff08;3DGS&#xff09;&#xff1b;当FLAME mesh被驱动时&#xff0c;3DGS根据它的父亲三角面片&#xff0c;做平移、旋转和缩放变化&#xff1b;3DGS可以视作mesh上的辐射场&#xff1…

「Vue3面试系列」Vue3.0的设计目标是什么?做了哪些优化?

文章目录 一、设计目标1.1 更小1.2 更快1.3更友好 二、优化方案2.1 源码2.11源码管理2.22 TypeScript 2.2 性能2.3 语法 API2.31逻辑组织2.32 逻辑复用 参考文献 一、设计目标 不以解决实际业务痛点的更新都是耍流氓&#xff0c;下面我们来列举一下Vue3之前我们或许会面临的问…

校园转转二手市场源码+Java二手交易市场整站源码

源码介绍 校园转转二手市场源码分享&#xff0c;Java写的应用&#xff0c;mybatis-plus 和 Hibernate随心用 后台地址&#xff1a;/home/index/index 账号密码&#xff1a;admin/123456 前台地址&#xff1a;/system/login

计算机网络2

OSI参考模型七层&#xff1a; 1.应用层 2.表示层 3.会话层 4.传输层 5.网络层 6.数据链路层 7.物理层 TCP/IP模型 5层参考模型

Apipost检测接口工具的基本使用方法

&#x1f440; 今天言简意赅的介绍一款和postman一样好用的后端接口测试工具Apipost 专门用于测试后端接口的工具&#xff0c;可以生成接口使用文档官方下载网站&#xff1a;http://www.apipost.cn 傻瓜式安装—>register->项目->创建项目->APIs->新建目录&…

Linux Docker本地部署WBO在线协作白板结合内网穿透远程访问

文章目录 前言1. 部署WBO白板2. 本地访问WBO白板3. Linux 安装cpolar4. 配置WBO公网访问地址5. 公网远程访问WBO白板6. 固定WBO白板公网地址 前言 WBO在线协作白板是一个自由和开源的在线协作白板&#xff0c;允许多个用户同时在一个虚拟的大型白板上画图。该白板对所有线上用…

LeetCode刷题--- 全排列 II

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言&#xff1a;这个专栏主要讲述递归递归、搜…

回归预测 | MATLAB实现GA-LSSVM基于遗传算法优化最小二乘向量机的多输入单输出数据回归预测模型 (多指标,多图)

回归预测 | MATLAB实现GA-LSSVM基于遗传算法优化最小二乘向量机的多输入单输出数据回归预测模型 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现GA-LSSVM基于遗传算法优化最小二乘向量机的多输入单输出数据回归预测模型 &#xff08;多指标&#…

ISCTF(b)

test_nc nc_shell ls cat flag 这两道题比较像 你说爱我&#xff1f;尊嘟假嘟 打开后重复出现 “ 你说爱我 ” “ 尊嘟 ” “ 假嘟 ” 。判断为 Ook 加密 , 将 “ 你说爱我 ” 替换为 “Ook.” &#xff1b; “ 尊嘟 ” 替换为&#xff1a; “Ook!” &#xff1b; “ 假嘟…

mysql函数(二)之常见字符串函数

MySQL中常见的字符串函数有以下几种&#xff1a; CONCAT()&#xff1a;将两个或多个字符串连接在一起。 用法&#xff1a;CONCAT(string1, string2, ...) 效果图&#xff1a; LENGTH()&#xff1a;返回字符串的长度。 用法&#xff1a;LENGTH(string) 效果图&#xff1a; U…

教你如何使用天眼销查企业客户

天眼销是一款能够帮助客户获取最新的企业联系方式、工商信息等关键数据的平台。 平台基于先进的技术和大数据解决方案&#xff0c;深入挖掘和分析企业信息&#xff0c;能够高效地收集、整理和存储各类企业数据&#xff0c;为用户提供360度视角和洞察&#xff1b;提供全面、准确…

【算法与数据结构】LeetCode55、45、跳跃游戏 I 、II

文章目录 一、跳跃游戏I二、跳跃游戏II三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、跳跃游戏I 思路分析&#xff1a;本题目标是根据跳跃数组的元素&#xff0c;判断最终能够到达数组末端。我们引入了一个跳跃范围…

跨境电商的未来工作方式:远程团队与全球协作

随着数字化时代的来临&#xff0c;跨境电商行业在不断演变&#xff0c;其未来工作方式也呈现出新的趋势。本文将探讨跨境电商未来的工作方式&#xff0c;聚焦于远程团队与全球协作的发展&#xff0c;以揭示这一变革如何重新定义企业的组织结构和工作模式。 远程团队的崛起 近年…

Leetcode—859.亲密字符串【简单】

2023每日刷题&#xff08;六十三&#xff09; Leetcode—859.亲密字符串 &#x1f4a9;山实现代码 class Solution { public:bool buddyStrings(string s, string goal) {int len1 s.size(), len2 goal.size();int cnt 0;int flag 0;int flag2 0;int odd -1;int a[26] …

双指针——找到字符串中的所有字母异位词

https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/?envTypestudy-plan-v2&envIdtop-100-liked 双指针&#xff0c;每次都统计出来p长度的滑动窗口里的数字,拿Arrays.equals进行对比,然后滑动一小格&#xff0c;减1加1继续比对即可。 class Solut…

VS2019, mfc,c++和halcon 2022调试的时候,查询halcon变量的值, 一直提示未为 halconcpp.dll 加载任何符号

在调试看值的过程中&#xff0c;发现这里看不到变量的值。 可以使用halcon变量检查工具查看。

Leetcode—96.不同的二叉搜索树【中等】

2023每日刷题&#xff08;六十四&#xff09; Leetcode—96.不同的二叉搜索树 算法思想 实现代码 class Solution { public:int numTrees(int n) {vector<int> G(n 1, 0);G[0] 1;G[1] 1;for(int i 2; i < n; i) {for(int j 1; j < i; j) {G[i] G[j - 1] * …