命令模式-C++实现

命令模式是一种行为型设计模式,它将请求封装成一个对象,从而能使你可以用不同的请求对客户端进行参数化。该模式允许请求的发送者和接收者进行解耦,发送者不需要知道接收者的信息,只需要通过命令对象来与它进行交互。

命令模式有四个角色:

1、抽象命令:它定义了执行操作的接口,包含一个执行方法和一个可选的撤销操作,这里的撤销是撤销命令,恢复成上一个命令执行的结果。

2、具体命令:实现了命令接口,持有接收者对象的引用,负责在接收者上执行操作。

3、接收者:执行命令所代表的操作

4、调用者:持有命令对象,发送请求并触发命令执行。

举例:

使用遥控器控制电灯的开和关。

#include <iostream>
#include <memory>// 接收者-电灯
class Light
{
public:void On(){std::cout << "电灯已经打开" << std::endl;}void Off(){std::cout << "电灯已经关闭" << std::endl;}
};// 抽象命令
class ICommand
{
public:virtual ~ICommand() {}virtual void Execute() = 0;virtual void Undo() = 0;protected:std::shared_ptr<Light> light_;
};// 具体命令-打开电灯
class CloseLight: public ICommand
{
public:CloseLight(std::shared_ptr<Light> _light){light_ = _light;}virtual void Execute() override{light_->On();}virtual void Undo() override{light_->Off();}
};// 具体命令-关闭电灯
class OpenLight: public ICommand
{
public:OpenLight(std::shared_ptr<Light> _light){light_ = _light;}virtual void Execute() override{light_->Off();}virtual void Undo() override{light_->On();}
};// 调用者-遥控器
class RemoteControl
{
public:void SetCommand(std::shared_ptr<ICommand> _command){command_ = _command;}void PressButton(){if(command_)command_->Execute();}void Undo(){if(command_)command_->Undo();}private:std::shared_ptr<ICommand> command_;
};

示例中,我们首先定义了一个抽象命令接口(ICommand),定义了两个方法Exectue()和Undo(),分别用于执行操作和撤销命令。

然后我们又创建了两个具体的命令类(OpenLight)和(CloseLight),分别实现了这两个方法。这些具体命令类会持有对接收者对象(Light)的引用,通过执行方法调用相应的操作。

最后创建了一个调用者角色(RemoteControl)作为遥控器。遥控器持有一个命令对象,提供设置命令对象和触发命令的执行方法。通过按下(PressButton)执行具体的命令,通过Undo撤销命令。

测试:

void TestCommand()
{// 创建接收者std::shared_ptr<Light> light = std::make_shared<Light>();// 创建命令std::shared_ptr<ICommand> openLight = std::make_shared<OpenLight>(light);std::shared_ptr<ICommand> closeLight = std::make_shared<CloseLight>(light);// 创建调用者std::shared_ptr<RemoteControl> remoteControl = std::make_shared<RemoteControl>();// 设置命令remoteControl->SetCommand(openLight);remoteControl->PressButton();remoteControl->Undo();remoteControl->SetCommand(closeLight);remoteControl->Undo();
}

测试代码中,我们创建了两个具体命令:打开电灯和关闭电灯、一个接收者,也就是电灯、一个遥控器对象。

通过遥控器设置命令,按下按钮,就可以执行具体的命令。

输出结果:

电灯已经打开
电灯已经关闭
电灯已经打开

可以看到,我们先设置命令为打开电灯,按下按钮,电灯已经打开,执行撤销方法,电灯就被关闭,然后我们设置命令为关闭电灯,执行撤销方法,电灯就被打开。

所以这里的撤销其实是撤销当前命令

命令模式遵顼的设计原则:

1、单一职责原则:每个命令类负责执行一个特定的命令。

2、开放封闭原则:可以动态的添加或删除命令,不影响现有代码。

3、里氏替换原则:命令模式中的具体命令类是抽象命令的子类,因此可以通过具体命令类的替换来扩展和改变命令的行为。

4、接口隔离原则:命令模式通过抽象命令和具体命令的设计,可以将不同的请求封装成不同的命令类,从而避免大量的接口在同一个类中定义。

优点:

1、解耦对象间的关系:命令模式将请求者和接收者解耦,使得命令发送者只需要知道抽象命令类,不需要知道具体的接收者,降低了系统的耦合度。

2、容易扩展新的命令:新增一个命令非常容易,不需要修改现有代码,符合开闭原则。

3、支持撤销和重做操作:命令模式可以将命令对象存储在历史记录中,实现命令的撤销和重做

4、支持队列请求和日志化请求:命令模式可以将命令对象放入队列中,实现对请求的排队和延迟执行,还可以将命令对象做持久化处理,实现对请求的日志记录。

缺点:

1、增加了系统的复杂度:引入了多个命令类、接收者类、调用类,增加了系统的复杂度。

2、可能会使类膨胀:每个命令都需要一个具体的命令类去实现,如果命令太多,就会造成类的数量过于膨胀,增加了系统的维护成本。

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

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

相关文章

力扣题:字符串的反转-11.23

力扣题-11.23 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;557. 反转字符串中的单词 III 解题思想&#xff1a;先读取单词&#xff0c;然后将单词进行翻转即可 class Solution(object):def reverseWords(self, s):""":type s…

2024年AMC8美国初中数学竞赛最后一个月复习指南(附资料)

还有一个半月的时间&#xff0c;2024年AMC8&#xff08;大家默认都直接叫这个比赛的英文名&#xff0c;而不叫中文名美国数学竞赛或美国初中数学竞赛了&#xff09;就要开始了。 有志于在2024年AMC8的比赛中拿到奖项的孩子已经在“磨拳霍霍”了。那么最后一个半月的时间该如何…

LeetCode刷题---反转链表

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏&#xff1a;http://t.csdnimg.cn/ZxuNL http://t.csdnimg.cn/c9twt 前言&#xff1a;这个专栏主要讲述递归递归、搜索与回溯算法&#xff0c;所以下面题目主要也是这些算法做的 我讲述…

Linux 进程状态

操作系统学科的进程状态 新建态&#xff1a;刚刚创建的进程&#xff0c; 操作系统还未把它加入可执行进程组&#xff0c; 它通常是进程控制块已经创建但还未加载到内存中的新进程。就绪态&#xff1a;进程做好了准备&#xff0c;只要有机会就开始执行。阻塞态&#xff1a;进程在…

Qt+ROS+ubuntu18.04配置教程(带界面)

1. 安装ROS Qt Creator Plug-in 首先安装ROS Qt Creator Plug-in&#xff0c;这其实是一个带有ROS插件的Qt Creator&#xff1a;去下面的网址https://ros-qtc-plugin.readthedocs.io/en/latest/_source/How-to-Install-Users.html#qt-installer-procedure&#xff0c;根据自己…

【开题报告】基于SpringBoot的在线打印预约系统的设计与实现

1.研究背景 随着信息技术的不断发展&#xff0c;大学校园中的打印服务已成为学生和教职员工经常需求的服务之一。然而&#xff0c;传统的打印服务存在排队等候、效率低下以及资源浪费等问题。为了提高打印服务的效率和便利性&#xff0c;基于Spring Boot的在线打印预约系统成为…

LeetCode 每日一题 Day1

1094. 拼车 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数组 trips , trip[i] [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi 乘客&#xff0c;接…

Java数据结构 之 包装类简单认识泛类

生命不息&#xff0c;奋斗不止 目录 1. 什么是包装类&#xff1f; 1.1 装箱和拆箱 1.2 自动装箱和自动拆箱 2. 什么是泛型 3. 引出泛型 3.1 语法 4 泛型类的使用 4.1 语法 4.2 示例 4.3 类型推导(Type Inference) 5. 裸类型(Raw Type) &#xff08;了解&#xff09…

IPv6是趋势!如何在Windows上禁用或启用IPv6?有3种简单的方法

IPv6是IPv4的一个更加安全、可扩展和可靠的继任者。然而&#xff0c;这种较新的互联网协议与IPv4不向后兼容&#xff0c;并且大多数VPN服务提供商不支持IPv6协议。 Microsoft不建议用户禁用IPv6或其组件&#xff0c;除非他们需要解决网络问题。但是&#xff0c;如果你计划禁用…

MATLAB实战 | 求水仙花数

循环结构的基本思想是重复&#xff0c;即利用计算机运算速度快以及能进行逻辑控制的特点&#xff0c;重复执行某些语句&#xff0c;以满足大量的计算要求。虽然每次循环执行的语句相同&#xff0c;但语句中一些变量的值是变化的&#xff0c;而且当循环到一定次数或满足条件后能…

阿里云服务器活动:免费试用ECS,轻松搭建WordPress博客平台,送午睡毯及猫超卡

阿里云服务器免费试用3个月 &#xff0c;搭建WordPress博客平台&#xff0c;还送午睡毯及猫超卡。活动时间截止至12月8日 网址&#xff1a; 阿里云服务器薅羊毛 送午睡毯

软件理论——演进式架构设计

一、问题 市场环境急速变化&#xff0c;业务高速发展&#xff0c;架构设计也要不断演进&#xff0c;以适应业务需要&#xff1b;随着企业规模的壮大&#xff0c;架构设计的腐化无法避免&#xff0c;只能在演进中持续进化&#xff1b;架构可以在不破坏原有架构的基础上增量式变…

mac M系列芯片安装chatGLM3-6b模型

1 环境安装 1.1 mac安装conda. 下载miniconda&#xff0c;并安装 curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh sh Miniconda3-latest-MacOSX-arm64.sh1.2 创建虚拟环境并激活 创建名为chatglm3的虚拟环境&#xff0c;python版本为3.10…

Stream API 方法使用总结

文章目录 1.1、Stream介绍1.2、Stream创建对象&#xff08;1&#xff09;empty()方法&#xff08;2&#xff09;of()方法&#xff08;3&#xff09;Arrays.stream()方法&#xff08;4&#xff09;list.stream()方法 1.3、Stream中间方法&#xff08;1&#xff09;filter()方法&…

算法设计与实现--贪心篇

贪心算法 贪心算法是一种在每一步选择中都采取当前状态下最优决策的算法&#xff0c;以期望能够通过一系列局部最优的选择达到全局最优。贪心算法的关键是定义好局部最优的选择&#xff0c;并且不回退&#xff0c;即一旦做出了选择&#xff0c;就不能撤销。 一般来说&#xf…

opencv项目开发实战--填补字母的空白

目录 完成/填写字母 OpenCV C++ 完成opencv表中缺失的行 如何使用 OpenCV 获取图像中所有文本的位置? 完成/填写字母 OpenCV C++ 解决方案一: 您似乎已经对图像进行了

弦理论:技术视角下的宇宙密码

弦理论:技术视角下的宇宙密码 一、引言 弦理论,这个一度被认为是物理学终极理论的候选者,如今已成为了研究微观世界的关键工具。它主张宇宙的基本单元并非点状粒子,而是像弦一样的物体,这些弦以各种方式振动,对应着不同的基本粒子。本文将从技术角度深入探讨弦理论,包括…

pybind11教程

pybind11教程 文章目录 pybind11教程1. pybind11简介2. cmake使用pybind11教程3. pybind11的历史 1. pybind11简介 项目的GitHub地址为&#xff1a; pybind11 pybind11 是一个轻量级的头文件库&#xff0c;用于在 Python 和 C 之间进行互操作。它允许 C 代码被 Python 调用&am…

EtherCAT主站SOEM -- 7 -- SOEM之ethercatmain.h/c文件解析

EtherCAT主站SOEM -- 7 -- SOEM之ethercatmain.h/c文件解析 一 ethercatmain.h/c文件功能预览:1.1 ethercatmain里面的结构体1.2 ethercatmain里面的函数二 ethercatmain.h/c 文件的主要函数的作用:2.1 结构体介绍2.1.1 `ec_adaptert` 结构体:2.1.2 `ec_fmmut` 结构体:2.1.3 …

C语言-内存分配

内存分配 1. 引入 int nums[10] {0}; //对int len 10; int nums[len] {0}; //错是因为系统的内存分配原则导致的2. 概述 在程序运行时&#xff0c;系统为了 更好的管理进程中的内存&#xff0c;所以有了 内存分配机制。 分配原则&#xff1a; 2.1 静态分配 静态分配原…