设计模式之命令模式

news/发布时间2024/5/15 4:35:53
设计模式专栏: http://t.csdnimg.cn/4Mt4u

相关系列文章

面向对象设计之接口隔离原则

设计模式之命令模式

设计模式之组合模式

设计模式之策略模式

设计模式之责任链模式

设计模式之桥接模式

设计模式之装饰器模式

设计模式之工厂模式

设计模式之空对象模式

设计模式之观察者模式

设计模式之单例模式

设计模式之过滤器模式

设计模式之适配器模式

设计模式之迭代器模式

浅谈架构设计

目录

1.概述      

2.结构

3.实现

4.使用场景

5.总结


1.概述      

        命令模式(Command Pattern)是对命令的封装,每一个命令都是一个请求操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行该操作。命令模式解耦了请求方和接收方,请求方只需请求执行命令,不用关心命令是怎样被接受,怎样被操作以及是否被执行等。命令模式属于行为型模式。

        命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请 求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

        在软件系统中,行为请求者与行为实现者通常是一种紧耦合关系,因为这样的实现简单明了。但紧耦合关系缺乏扩展性,在某些场合中,当需要为行为进行记录,撤销或重做等处理时,只能修改源码。而命令模式通过为请求与实现间引入了一个抽象命令接口,解耦了请求与实现,并且中间件是抽象的,它可以有不同的子类实现,因此其具备扩展性。所以,命令模式的本质是解耦命令请求与处理。

2.结构

命令模式的核心在于引入了命令类,通过命令类来降低发送者和接收者的耦合度,请求发送者只需指定一个命令对象,再通过命令对象来调用请求接收者的处理方法,其结构如图所示:

角色定义:

抽象命令类(Command)角色: 抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的 execute() 等方法,通过这些方法可以调用请求接收者的相关操作。

具体命令(Concrete Command)角色:具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现 execute() 方法时,将调用接收者对象的相关操作(action)

实现者/接收者(Receiver)角色:  接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

调用者/请求者(Invoker)角色: 调用者即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的 execute() 方法,从而实现间接调用请求接收者的相关操作。

客户端(Client)角色创建具体命令对象并设置其接收者,将命令对象交给调用者执行。

        命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命令的责任分割开。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行相应的操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执行、何时被执行,以及是怎么被执行的。

3.实现

        命令模式的关键在于引入了抽象命令类,请求发送者针对抽象命令类编程,只有实现了抽象命令类的具体命令才与请求接收者相关联。在最简单的抽象命令类中只包含了一个抽象的 execute() 方法,每个具体命令类将一个 Receiver 类型的对象作为一个实例变量进行存储,从而具体指定一个请求的接收者,不同的具体命令类提供了 execute() 方法的不同实现,并调用不同接收者的请求处理方法。

        典型的抽象命令类代码如下:

class ICommand
{
public:virtual ~ICommand() {}virtual void execute() = 0;
};

        请求接收者 Receiver 类具体实现对请求的业务处理,它提供了 action() 方法,用于执行与请求相关的操作,其典型代码如下:

class CReceiver
{
public:void action() {//具体操作std::cout << "CReceiver::action..." << std::endl;}
};

        具体命令类继承了抽象命令类,它与请求接收者相关联,实现了在抽象命令类中声明的 execute() 方法,并在实现时调用接收者的请求响应方法 action(),代码如下:

class CConcreteCommand : public ICommand
{
public:explicit CConcreteCommand(CReceiver* pReceiver) : m_pReceiver(pReceiver) {}void execute() override {m_pReceiver->action();}private:CReceiver* m_pReceiver;
};

        对于请求发送者即调用者而言,将针对抽象命令类进行编程,可以通过构造注入或者设值注入的方式在运行时传入具体命令类对象,并在业务方法中调用命令对象的 execute() 方法,其典型代码如下:

class CInvoker {
public:CInvoker(ICommand* cmd) {m_pCommand = cmd;}void setCommand(ICommand* cmd) { m_pCommand = cmd; }// 业务方法 用于调用命令类的 execute() 方法void doWork() {m_pCommand->execute();}private:ICommand* m_pCommand;
};

测试用例:

int main()
{std::unique_ptr<CReceiver> pReceiver(new CReceiver);std::unique_ptr<ICommand> pCommand(new CConcreteCommand(pReceiver.get()));std::unique_ptr<CInvoker> pCaller(new CInvoker(pCommand.get()));pCaller->doWork();return 0;
}

输出:CReceiver::action...

4.使用场景

1.系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
2.现实语义中具备“命令”的操作(如命令菜单、shell命令等)。
3.系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
4.系统需要在不同的时间指定请求、将请求排队和执行请求。
5.需要支持命令宏(即命令组合操作)。

5.总结

优点

1.解耦:命令模式将请求的发送者和接收者解耦,请求的发送者不需要知道接收者的具体实现细节,只需要通过命令对象来发送请求。
2.可撤销操作:命令模式支持可撤销的操作,通过将命令对象存储在历史记录中或者在命令对象中实现撤销操作,可以实现操作的撤销。
3.日志记录:命令模式可以方便地记录请求的历史,例如将命令对象存储在日志中以便于后续的审计和回溯。
4.支持事务:命令模式可以支持事务,通过将多个命令组合成一个更大的操作,可以保证这些命令要么全部执行,要么全部不执行。
5.方便添加新操作:新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码甚至客户类代码,满足开闭原则的要求。

缺点

使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。

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

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

相关文章

golang学习2,golang开发配置国内镜像

go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,direct

2024水科技大会暨技术装备成果展览会——城镇雨污分流及污水处理提质增效论坛(五)

为积极应对“十四五”期间我国生态环境治理面临的挑战&#xff0c;加快生态环境科技创新&#xff0c;构建绿色技术创新体系&#xff0c;全面落实科学技术部、生态环境部等部委编制的《“十四五”生态环境领域科技创新专项规划》&#xff0c;积极落实四川省人民政府与上海大学《…

Qt C++春晚刘谦魔术约瑟夫环问题的模拟程序

什么是约瑟夫环问题&#xff1f; 约瑟夫问题是个有名的问题&#xff1a;N个人围成一圈&#xff0c;从第一个开始报数&#xff0c;第M个将被杀掉&#xff0c;最后剩下一个&#xff0c;其余人都将被杀掉。例如N6&#xff0c;M5&#xff0c;被杀掉的顺序是&#xff1a;5&#xff…

Leetcoder Day24| 回溯part04:组合+分割

93.复原IP地址 给定一个只包含数字的字符串&#xff0c;复原它并返回所有可能的 IP 地址格式。 有效的 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.…

etcdctl查看k8s资源信息

背景 k8s中的网络配置和对象状态信息都会保存到etcd中&#xff0c;所以我们可以通过etcdctl查看保存在数据库中的信息 常用操作 查看etcd的各个节点的状态 [rootmaster3 ~]# etcdctl --endpoints"10.197.115.27:2379,10.197.115.25:2379,10.197.115.26:2379" --ca…

搭建XSS 测试平台

XSS 测试平台是测试XSS漏洞获取cookie并接收Web 页面的平台&#xff0c;XSS 可以做 JS能做的所有事&#xff0c;包括但不限于窃取cookie、后台增删改文章、钓鱼、利用XSS漏洞进 行传播、修改网页代码、网站重定向、获取用户信息(如浏览器信息、IP 地址)等。这 里使用的是基于x…

阿里面试:最佳线程数,如何确定?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein 希音、百度、网易的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 如何确定系统的最佳线程数&#xff1f; 小伙伴 没有回…

使用Docker快速简单部署Rsshub工具并结合内网穿透远程访问RSS订阅源

文章目录 1. Docker 安装2. Docker 部署Rsshub3. 本地访问Rsshub4. Linux安装Cpolar5. 配置公网地址 Rsshub是一个开源、简单易用、易于扩展的RSS生成器&#xff0c;它可以为各种内容生成RSS订阅源。 Rsshub借助于开源社区的力量快速发展&#xff0c;目前已适配数百家网站的上千…

第九届大数据与计算国际会议 (ICBDC 2024) 即将召开!

2024年第九届大数据与计算国际会议&#xff08;ICBDC 2024&#xff09;将于2024年5月24至26日在泰国曼谷举行。本次会议由朱拉隆功大学工程学院工业工程系主办。ICBDC 2024的宗旨是展示大数据和计算主题相关科学家的最新研究和成果&#xff0c;为来自不同地区的专家代表们提供一…

美创科技荣获“2023年网络安全国家标准优秀实践案例”

近日&#xff0c;全国网络安全标准化技术委员会正式公布2023年网络安全国家标准优秀实践案例获奖名单。 杭州美创科技股份有限公司&#xff08;以下简称&#xff1a;美创科技&#xff09;申报的“GB/T 20281-2020《信息安全技术 防火墙安全技术要求和测试评价方法》在政企领域数…

sql-labs32关宽字节注入

一、环境 网上有自己找很快 二、如何通关 2.1解释 虚假预编译没有参数绑定的过程&#xff0c;真实预编译有参数绑定的过程 宽字节注入出现的本质就是因为数据库的编码与代码的编码不同&#xff0c;导致用户可以通过输入精心构造的数据通过编码转换吞掉转义字符。 在32关中…

构建React TodoList应用:管理你的任务清单

构建React TodoList应用&#xff1a;管理你的任务清单 在日常生活和工作中&#xff0c;任务管理是一项至关重要的任务。为了更好地组织和管理我们的工作和生活&#xff0c;我们需要一个高效而简单的任务管理工具。本文将介绍如何使用React框架构建一个功能丰富的TodoList应用&…

C# CAD2016 cass10宗地Xdata数据写入

一、 查看cass10写入信息 C# Cad2016二次开发获取XData信息&#xff08;二&#xff09; 一共有81条数据 XData value: QHDM XData value: 121321 XData value: SOUTH XData value: 300000 XData value: 141121JC10720 XData value: 权利人 XData value: 0702 XData value: YB…

【前沿热点视觉算法】-面向显著目标检测的注意区域空间金字塔池网络

计算机视觉算法分享。问题或建议&#xff0c;请文章私信或者文章末尾扫码加微信留言。 1 论文题目 面向显著目标检测的注意区域空间金字塔池网络 2 论文摘要 显著目标检测&#xff08;SOD&#xff09;的最新进展主要依赖于空间空间金字塔池&#xff08;ASPP&#xff09;模块…

经典Go知识点总结

开篇推荐 来来来,老铁们,男人女人都需要的技术活 拿去不谢:远程调试,发布网站到公网演示,远程访问内网服务,游戏联机 推荐链接 1.无论sync.Mutex还是其衍生品都会提示不能复制,但是能够编译运行 加锁后复制变量&#xff0c;会将锁的状态也复制&#xff0c;所以 mu1 其实是已…

Linux运维-Web服务器的配置与管理(PHP)

Web服务器的配置与管理(PHP) 项目场景 某企业在CentOS上搭建Web服务系统&#xff0c;以PHP作为网页开发环境&#xff0c;以MySQL为后台数据库。 基础知识 PHP PHP原始为Personal Home Page的缩写&#xff0c;已经正式更名为 “PHP: Hypertext Preprocessor”&#xff08;超…

正则表达式

用于匹配字符串中字符组合的模式。在js中&#xff0c;正则表达式也是对象 使用场景&#xff1a; 输入框的输入限制等。 语法&#xff1a; 判断是否有符合规则的字符串&#xff1a; test()检测是否匹配 了解&#xff1a;exec&#xff08;&#xff09; 匹配成功返回数组&…

【SQL注入】靶场SQLI DUMB SERIES-24通过二次注入重置用户密码

先使用已知信息admin/admin登录进去查下题&#xff0c;发现可以修改密码 猜测可能存在的SQL语句&#xff1a;UPDATE user SET password新密码 WHERE user用户名 and password旧密码 假设我们知道有个admin用户&#xff0c;但是不知道其密码&#xff0c;如何可以将其密码重置&…

【GPTs分享】GPTs分享之Write For Me

Write For Me 是一个专门定制的GPT版本&#xff0c;旨在为用户提供高质量的文本内容创作服务。它适用于各种写作需求&#xff0c;从商业计划、学术文章到创意故事等。下面是从简介、主要功能、使用案例、优点和局限性几个方面对Write For Me 的详细介绍。 简介 Write For Me …

图片转PDF

选择图片右键——打开方式 ——照片、画图、截图工具 其他的选择性尝试 点击打印 在刚刚保存的路径哪里即可得到刚刚保存的PDF版的图片
推荐文章