【深入浅出设计模式--命令模式】

深入浅出设计模式--命令模式

  • 一、背景
  • 二、问题
  • 三、解决方案
  • 四、试用场景总结
  • 五、后记

一、背景

  命令模式是一种行为设计模式,它可以将用户的命令请求转化为一个包含有相关参数信息的对象,命令的发送者不需要知道接收者是如何处理这条命令,多个功能入口可以发送同一命令,避免多处多次实现相同功能的冗余代码。另外可以对命令进行延迟处理,或放入队列或栈中,支持命令回撤。

二、问题

  在使用GUI界面的应用程序时,一般保存功能会有多个入口,比如点击按钮保存、点击菜单项保存和使用键盘ctrl+s保存等,每个入口的位置不同且没有什么关联关系,只是最终实现文档保存功能的代码是一样的。
在这里插入图片描述
  此时要么将这些操作代码复制粘贴进多个类中,要么就是让菜单项依赖于按钮,显然这两种方式都是不明智的。

三、解决方案

  一般在这种一对多、多对多的场景下,最好的方式是添加一个中间层,上层负责GUI的交互,下层负责业务逻辑的处理,中间层则将命令请求抽象为一个对象,在上下两层中传递消息数据,该对象可以连接不同的GUI和业务逻辑对象GUI 对象无需了解业务逻辑对象是否获得了请求,也无需了解其对请求进行处理的方式。
在这里插入图片描述
  1. 该模式的类图如下所示:发送者ICommandSender中包含了命令接口ICommand的指针,ICommand中只有execute虚函数,具体的命令类SaveCommand中包含有命令接收者Document的指针,且重写execute函数。CommandHistory类记录了每条执行了的命令,调用pop弹出命令时可以调用该命令的redo函数(下图中未展示)进行命令撤销。
在这里插入图片描述

  2. 该模式下各类之间交互的时序图如下:首先生成命令接收者Document,然后生成命令SaveCommand并绑定Document,接下来生成命令发送者Button并绑定SaveCommand,最后Button调用触发函数click让命令对象去执行具体的execute函数。
在这里插入图片描述
  3. 相关代码实现

  • 命令发送者
class CommandHistory{
public:static CommandHistory* GetInstance(){static CommandHistory cmdHis;return &cmdHis;}void push(ICommand* cmd){m_cmdHisVec.push(cmd);}void pop(){m_cmdHisVec.pop();}size_t size(){return m_cmdHisVec.size();}
private:stack<ICommand*> m_cmdHisVec;
};#define CMD_HIS CommandHistory::GetInstance()class ICommandSender{
public:ICommandSender(){}~ICommandSender(){}void setCommand(ICommand* cmd){m_cmd = cmd;}ICommand* getCommand(){return m_cmd;}
protected:ICommand* m_cmd;
};class Button : public ICommandSender{
public:void click(){m_cmd->execute("Sent by Button");CMD_HIS->push(m_cmd);cout << "Count of Button history command is " << CMD_HIS->size() << endl;}
};class Shortcut : public ICommandSender{
public:void setCommand(const string& key, ICommand* cmd){m_cmd = cmd;m_keyCmdMap[key] = cmd;}void press(){m_cmd->execute("Sent by Shortcut");CMD_HIS->push(m_cmd);cout << "Count of Shortcut history command is " << CMD_HIS->size() << endl;}
private:map<string, ICommand*> m_keyCmdMap;
};
  • 命令
class ICommand{
public:virtual ~ICommand(){}virtual void execute(const string& from) = 0;
};
class SaveCommand : public ICommand{
public:SaveCommand(Document* doc) : m_doc(doc) {}virtual void execute(const string& from) override{m_doc->setText(from);m_doc->save();}
private:Document* m_doc;
};
  • 命令接收者
class Document{
public:void setText(const string& text){m_text = text;}void save(){cout << m_text << " has been saved" << endl;               }
private:string m_text;
};

四、试用场景总结

  • 多个不同操作对应同一处理结果,那么可以使用命令模式。如点击菜单项、点击按钮和ctrl+s进行保存
  • 同一操作在不同的场景下产生不同的结果,在运行时切换已连接的命令,也可以使用命令模式。如用户可以配置菜单项,在点击时触发不同的命令。
  • 若需要将操作放入队列中,延迟或计划发送命令,也可以使用命令模式。
  • 若要实现操作回滚(撤销)功能,也可以使用命令模式。命令历史记录是一种包含所有已执行命令对象及其相关程序状态备份的栈结构。
  • 若要远程执行命令,需要将命令对象序列化,从而能方便地写入文件或数据库中。

五、后记

以上所有内容均为原创,代码已上传至gayhub:
https://github.com/gangster-puppy/Design-Pattern.git

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

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

相关文章

php文件上传功能(文件上传)

实现文件上传是Web开发中常用的功能之一&#xff0c;而PHP也是支持文件上传的。那么&#xff0c;下面我们就来介绍一下常用的PHP实现文件上传的方法。 使用HTML表单实现文件上传 HTML表单是Web开发中最基本的元素之一&#xff0c;它可以接收用户输入的数据&#xff0c;并通过…

Python 笔记03(多线程)

一 打开命令行&#xff0c;查看本机IP windows r 命令行输入&#xff1a;cmd ipconfig 然后查看IPv4的地址&#xff1a;192.168.1*6.1 ipconfig 二 函数式多进程 from multiprocessing import Process import os, timedef func(name):print(进程的ID&#xff1a;, os.g…

大数据时代,数据治理

一、大数据时代还需要数据治理吗&#xff1f; 数据平台发展过程中随处可见的数据问题 大数据不是凭空而来&#xff0c;1981年第一个数据仓库诞生&#xff0c;到现在已经有了近40年的历史&#xff0c;相对数据仓库来说我还是个年轻人。而国内企业数据平台的建设大概从90年代末…

Docker 自动化部署(保姆级教程)

Docker 自动化部署 1. jenkins 介绍1.1 参考链接&#xff1a;1.2 jenkins 概述1.3 jenkins部署项目的流程 2. jenkins 安装2.1 基于docker 镜像2.2 启动 jenkins 后端服务2.3 登录 jenkins 服务后端 3. jenkins自动化部署开始3.1 下载需要的插件3.2 创建任务3.2.1 描述3.2.2 配…

使用bash脚本编译Qt工程

最近在搭建Qt工程的编译服务器&#xff0c;需要通过shell脚本执行工程的编译过程&#xff0c;写在这里&#xff0c;总结最近的工作。 1. 构建过程 以Windows为例&#xff0c;在QtCreator中左侧选择“项目”便可以看到编译的指令和参数&#xff0c;这些操作也会在我们点击“构建…

git管理常用命令

1、下载代码 git clone 地址2、软件代码提交 1、查看工程中被修改的文件&#xff1a;git status 2.将不需要提交的文件回退&#xff1a;git check <文件路径> 3.更新工程到最新&#xff1a;git pull 4.将本地代码添加到暂存区&#xff1a;git add <将要提交的文件路…

CAN总线数据链路层

CAN报文帧种类: 数据帧:用于发送节点向接收节点传送数据,是使用最多的帧类型远程帧:用于接收节点向某个发送节点请求数据错误帧:用于当某节点检测出错误时向其他节点通知错误的帧过载帧:用于接收节点向发送节点通知自身接收能力的帧帧间隔:将数据帧或远程帧与前面的帧分…

MySQL学习笔记14

MySQL查询之多表查询&#xff1a;&#xff08;了解&#xff09;但是还是要掌握比较好。 1、什么是多表查询&#xff1f; 查询五子句是单表查询&#xff0c;实际工作中&#xff0c;也可能会接触到一个复杂的多表查询。 2、Union 联合查询&#xff1a; union联合查询的作用&…

ElementUI之首页导航与左侧菜单

目录 一、Mock 1.1 什么是Mock.js 1.2 安装与配置 1.2.1 安装mock.js 1.2.2 引入mock.js 1.3 mock.js使用 1.3.1 定义测试数据文件 1.3.2 mock拦截Ajax请求 1.3.3 界面代码优化 二、总线 2.1 定义 2.2 类型分类 2.3 前期准备 2.4 配置组件与路由关系 2.4.1 配置…

Java8实战-总结35

Java8实战-总结35 重构、测试和调试使用 Lambda 重构面向对象的设计模式工厂模式 测试 Lambda 表达式测试可见 Lambda 函数的行为测试使用 Lambda 的方法的行为将复杂的 Lambda 表达式分到不同的方法高阶函数的测试 重构、测试和调试 使用 Lambda 重构面向对象的设计模式 工厂…

JSON数据获取指南!

在互联网时代&#xff0c;数据是金钱的来源。然而&#xff0c;要从海量的网页中提取需要的数据并不容易。本文将带你了解如何使用Node.js编写简易爬虫程序&#xff0c;帮助你轻松获取并处理JSON数据&#xff0c;让你不再为数据发愁。 一、准备工作 安装Node.js&#xff1a;确保…

如何在控制台打印sql语句

步骤一&#xff1a; log4j2.xml中做以下配置 <logger name"xxx.infrastructure.mysql.mapper"level"debug" additivity"false"><appender-ref ref"Console"/></logger>步骤二&#xff1a;IDEA下载Free Mybatis Plu…

9、JavaSE总结

9、JavaSE总结 9.1 Java语言 9.1.1 MarkDown语法 9.1.2 简单的Dos命令 9.1.3计算机语言发展 9.1.4 Java的诞生 1995年诞生&#xff1a;JavaSE、JavaME、JavaEE 2006年Hadoop大数据系列 9.1.5 JDK、JRE JDK&#xff1a;开发者工具包、配置环境变量&#xff08;配置Java…

Vue Mock.js介绍和使用与首页导航栏左侧菜单搭建

前言&#xff1a; 因为使用Vue开发&#xff0c;组件写的太多&#xff0c;组件与组件之间的传递数据复杂&#xff0c;所以要用到Mock和Bus事件 一&#xff0c;关于Mock 1.1.什么是Mock.js Mock.js是一个模拟数据的生成器&#xff0c;用来帮助前端调试开发、进行前后端的原型分离…

upload-labs靶场未知后缀名解析漏洞

upload-labs靶场未知后缀名解析漏洞 版本影响&#xff1a; phpstudy 版本&#xff1a;5.2.17 ​ 1 环境搭建 1.1 在线靶场下载&#xff0c;解压到phpstudy的www目录下&#xff0c;即可使用 https://github.com/c0ny1/upload-labs1.2 已启动&#xff1a;访问端口9000&…

似然和概率

前言 高斯在处理正态分布的首次提出似然&#xff0c;后来英国物理学家&#xff0c;费歇尔 概率是抛硬币之前&#xff0c;根据环境推断概率 似然则相反&#xff0c;根据结果推论环境 P是关于x的函数&#xff0c;比如x为正面朝上的结果&#xff0c;或者反面朝上的结果&#xf…

数据大爆炸:大数据分析如何改变我们的世界

文章目录 大数据分析的基本概念数据的三个V大数据分析的技术 大数据分析在商业中的应用1. 个性化营销2. 风险管理3. 供应链优化4. 客户服务 大数据分析在医疗保健中的应用1. 疾病预测2. 患者治疗3. 医疗设备监控 大数据分析在科学研究中的应用1. 天文学2. 生物学3. 气象学 大数…

如何搭建自己的gitlab服务器

这里使用Termus工具连接服务器&#xff0c;然后根据步骤走即可&#xff01; 安装 1.配置yum源安装gitlab vim /etc/yum.repos.d/gitlab-ce.repo修改或新增下面配置并保存 [gitlab-ce] nameGitlab CE Repository baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum…

pycharm中配置torch

在控制台cmd中安装好torch后&#xff0c;在pycharm中使用torch&#xff0c;需要进行简单设置即可。 在pycharm中新建一个工程&#xff0c;在file文件中打开setting 在setting中找到project interpreter编译器 找到conda environment的环境配置&#xff0c;设置好相应的目录 新…

2023年蓝帽杯取证复现

案件介绍 2021 年 5 月&#xff0c;公安机关侦破了一起投资理财诈骗类案件&#xff0c;受害人陈昊民向公安机关报案称其在微信上认识一名昵称 为 yang88 的网友&#xff0c;在其诱导下通过一款名为维斯塔斯的 APP &#xff0c;进行投资理财&#xff0c;被诈骗 6 万余万元。接警…