设计模式6-命令模式(Command)解析+案例实践+总结

2023-11-11

本文是对面向对象设计模式--命令模式(Command)的解析,主要分为定义解析、通过餐厅点餐案例、遥控器案例讲解命令模式、多案例练习加深对命令模式的理解、最后总结知识要点。

第一篇:定义解析

命令模式是GoF四人帮整理的《设计模式-可复用面向对象软件基础》一书中23种设计模式中归类为行为型模式中的设计模式,23种设计模式根据它们的用途分为三大类:5种创建型模式、7种结构型模式、11种行为型模式。

引自GoF四人帮对命令模式(Command)的定义与类图:

将一个请求封装为一个对象,从而使你可用不同的请求对象对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

将一个请求封装为一个对象,从而使你可用不同的请求对象对客户进行参数化;这一句点出了命令模式的核心思想,客户发出一个请求就像发出一个命令或指指令一样,需要有接收者接收这个请求,然后进行处理。不同的请求,可能需要不同的接收者接收和处理,如智能家庭遥控器通过一个遥控器控制家里的各种电器,打开或关闭不同的电器,它的接收者是不同的,它必须由不同的电器去处理,为了实现将客户与这些具体接收者进行解耦,我们将请求封装成一个对象并增加一个调用者角色Invoker,将客户发出的不同请求封装成不同的命令对象,不同的命令对象包含着处理对应请求的各种接收者对象,将命令对象传递给调用者对象,由调用者对象去调用通知接收者处理请求,调用者就相当于遥控器,客户发出打开或关闭不同电器的请求,不同的请求被封装成不同的命令对象,遥控器调用不同的命令对象来通知不同的接收者即电器来处理这个打开或关闭的请求。这样也实现了用不同请求对客户进行参数化,同时也容易扩展,当有新的电器需要控制时,只需要为其封装一个对应的命令对象即可,客户端和调用者者不需要修改代码。

对请求排队或记录请求日志,以及支持可取消的操作;将请求封装成一个命令对象之后,可以在命令对象中添加日志,这些对象可以被传递或者使用队列进行排除执行,命令对象中可以实现相应的撤销方法,便可直接通过这个命令对象进行撤销请求。

 

第二篇:餐厅点餐案例

需求:客户填写点餐订单、餐厅服务员拿到订单,将订单放到订单柜台,并通知厨师开始准备餐点、厨师开始准备餐点、最后做出订单上的餐点。

需求分析:

一张订单封装了准备餐点的请求,把订单想象成一个用来请求准备餐点的对象,订单对象可以被传递;从女招待传递到订单柜台,然后喊一声“订单来了”就可以。

从面向对象角度分析点餐案例:

实现:

1、把订单封装成一个请求,订单请求中包含:餐点的内容、用于执行制作餐点的方法orderUp()和具体制作餐点的厨师的引用chef。

2、订单请求对象可以被传递,从客户传到了服务员,服务员调用订单中的执行制作餐点的方法orderUp()。

分析:

1)一张订单封装了准备餐点的请求,把订单想象成一个用来请求准备餐点的对象,订单对象可以被传递;

2)女招待的工作很简单,接下顾客的订单,然后将订单放到柜台,并调用orderUp()方法,通知厨师准备餐点。

3)厨师是一个对象,他真正知道如何准备餐点。一旦女招待调用orderUp()方法,厨师就接手,实现需要创建餐点的所有方法。

4)客户和厨师之间彻底解耦;女招待和厨师之间也彻底解耦;

通过这种实现方式:把“发出请求的对象”和“接受与执行这些请求的对象”分隔开来。

第三篇:遥控器案例

需求:

1)遥控器有七组开关按钮,还有一个撤销按钮。

2)这些开关按钮用来控制家电开关,如电灯、风扇、热水器、音响设备等。

3)我们希望能够创建一组遥控器的API,让每个开关按钮能够控制一个电器。

4)注意:要求提供扩展,能够方便未来添加新的电器控制开关。

需求分析:

1)目前有一个有很多开和关按钮的遥控器和很多不同的电器类。

2)分离关注点:遥控器应该知道如何解读按钮按下的动作,然后发出正确的请求;

3)但是遥控器不需要知道具体电器的处理细节,如如何打开热水器。

4)我们不必让遥控器知道太多具体电器类的细节。

采用命令模式实现:

1)命令模式可将“动作的请求者”从“动作的执行者”对象中解耦。请求者是用户、请求是按下的遥控器开关按钮的请求、执行者是具体的电器、遥控器是调用者。

2)客户发起开或关的请求、遥控器接收请求并调用相应的电器、电器进行相关的开或关操作。

3)把具体电器的开或关请求封装成请求对象,如打开电灯请求、关闭电灯请求等。每一个按扭就对应一个请求对象,按下按扭即调用请求的执行方法。

4)撤销按钮对应一个撤销请求,按下撤销按钮要调用对应请求的撤销方法。

当按下按钮的时候,就可以请命令对象做相关的工作。遥控器并不需要知道工作内容是什么,只要有个命令对象能和正确的对象沟通,把事情做好就可以了。所以,遥控器和电灯对象解耦了。

使用这个模式,我们能够创建一个API,将这些命令对象加载到对应的按钮开关,让遥控器的代码尽量保持简单。而把家电的工作和进行该工作的对象一起封装在命令对象中。

命令模式:

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可取消的操作。

1)Client客户:客户负责创建一个ConcreteCommand,并设置接收者Receiver。

2)Receiver接收者:知道如何进行必要的工作,实现这个接口,任何类都可以当接收者。

3)Command命令接口:为所有命令声明了一个接口。调用命令对象的execute()方法,就可以让接收者进行相关动作。这个接口也具备一个undo()撤销操作。

4)ConcreteCommand具体命令对象:定义了动作和接收者之间的绑定关系。调用者只要调用execute()就可以发出请求,然后由ConcreteCommand调用接收者的一个或多个动作。

5)Invoker调用者持有一个命令对象,并在某个时间点调用命令对象的execute()方法,将请求付诸实行。

6)命令对象将动作和接收者包进对象中。这个对象只暴露一个execute()方法,当此方法被调用的时候,接收者就会进行这些动作。从外面看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道调用execute()方法,请求的目的就能达到。

1)命令对象将动作和接收者包进对象中。

2)这个对象只暴露一个execute()方法,当此方法被调用的时候,接收者就会进行这些动作。

3)从外面看,其他对象不知道究竟哪个接收者进行了哪些动作,只知道调用execute()方法,请求的目的就能达到。

 

第四篇:案例实践

练习案例源码:https://github.com/chentian114/100-dayaction/tree/master/designpattern-1

OrderDemo点餐案例:

客户点餐,填写订单,招待员拿到订单将其放到订单栏,并通知厨师制作餐点。

RemoteControlDemo遥控器案例:

一个遥控器有多个按钮,每对按钮控制一个电器的开和关,以及支持撤销操作。并希望能够提供扩展。

AudioPlayerDemo盒式收音机案例:

用户有一个盒式录音机,此录音机有播音(Play)、倒带(Rewind)和停止(Stop)功能。

案例分析:录音机的键盘便是请求者(Invoker)角色;客户是客户端角色,而录音机便是接收者角色。Command类扮演抽象命令角色,而PlayCommand、StopCommand和RewindCommand便是具体命令类。用户不需要知道播音(play)、倒带(rewind)和停止(stop)功能是怎么具体执行的,这些命令执行的细节全都由键盘(Keypad)具体实施。用户只需要在键盘上按下相应的键便可以了。

GroupRequirementDemo项目组需求案例:

客户会提不同的需求到项目组如:增加一个需求、修改一项需求、删除一个页面,项目组要对这些需求进行处理。项目组分为:需求组、美工组、研发组。增加一个需求需要需求组、美工组、研发组参与。删除一个页面需要需求组与研发组删除参与。

需求分析:

将客户需求封装成命令,客户只需要关注其所提的需求即可,而不需要关注项目组具体处理该任务的项目组内部信息。项目组长接到用户需求,对客户需求进行参数化,如:增加一个需求就是一个新增需求的命令,删除一个页面的需求就是一个删除页面的命令。命令里持有处理该任务的组目组成员的引用,并有一个统一的execute()方法调用具体项目组成员处理该需求。

实践:在实际Receiver一般采用封闭的方式,减少Client对Receiver的依赖。如案例中的各Group组。

 

第五篇:总结

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

Receive接收者角色,处理命令

Command命令角色,需要执行的请求

Invoker调用者角色,接收命令,并执行命令

命令模式把请求的发送者和请求的执行分割开,委派给不同的对象。

客户端:创建一个具体的命令。请求者:负责调用命令对象执行请求。接收者:负责具体实施和执行一个请求。

命令模式的优点:

1)使得新的命令很容易加入到系统中

2)能容易的设计一个命令队列

3)可以容易实现撤销

4)可以容易地将命令记入日志

命令模式优点:

1)更松散的耦合,将发起命令的客户端与具体处理命令的接收者完全解耦,客户端完全不知道接收者是什么样子。

2)更动态的控制,把请求封装起来,可以动态的对请求进行参数化、队列化和日志化等,使系统更灵活。

3)复合命令,很容易的组合命令,即宏命令,使系统功能更强大。

4)更好的扩展,很容易添加新的命令。

优点:

1)类间解耦,调用者角色与接收者角色之间没有任何依赖关系。

2)可扩展性,Command子类可以非常容易扩展,调用者Invoker和高层次的Client不产一严重的代码耦合。

缺点:

1)类数量随命令数量增长而增长。可能造成类数量过多。

所谓宏命令简单点说就是包含多个命令的命令,是一个命令的组合。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式6-命令模式(Command)解析+案例实践+总结 的相关文章

  • 跳转后 vim 中自动 'zz'

    当我跳转到世界上的任何地方后 无论是在当前文件还是在不同的文件中 是否可以让vim自动运行zz 重新以当前行为中心 在搜索之类的事情之后我想要这个 ctrl o and ctrl i 以及几乎任何运动 除了hjkl Thanks Voila
  • 什么是 Programdata/Application Data 文件夹?

    因此 我正在编写一个迭代指定目录树的应用程序 并且我正在尝试处理文件夹访问权限的异常 并且我遇到了编译器返回的一个文件夹 其中包含 C ProgramData Application Data 目录 有谁知道这个文件夹是什么 它似乎不存在于
  • 如何从 Perl 将输入传送到 Java 命令?

    我需要通过 Java 程序运行一个字符串 然后检索输出 Java 程序通过标准输入接受字符串 以下作品 my output echo string java jar java program jar 有一个问题 string可以是任何东西
  • 在特定时间运行命令

    我正在尝试在特定时间运行命令 我看过 at 命令 但我不知道如何让它工作 这就是我所做的 at 1843 Enter php run this script php Ctrl D 但如何在 bash 脚本中执行此操作呢 我的意思是 我需要按
  • 如何在网页中动态显示 ping 输出?

    作为诊断页面的一部分 我希望用户能够运行 ping 即一个普通的 shell 命令 将 ICMP ECHO REQUST 发送到某个 IP 并在浏览器的 div 中动态显示结果 后端是 Ruby Rails 我已经在服务器端运行该命令并读取
  • 当用户控件可见时将焦点设置到它

    I am showing a MessageBox and want the user to be able to copy the contents of the message using CTRL C The problem is t
  • MVVM 中的事件而不是命令?

    在MVVM的各种教程中经常会指出 MVVM的目标不是消除代码隐藏 并且代码隐藏中的一些事件处理可能仍然是必要的 在什么场景下您需要在代码隐藏中编写事件而不是在视图模型中使用命令 一般来说 如果您的代码与 UI 逻辑相关 请将其保留在视图的
  • 如何在c#中使用net user

    我正在尝试将 net user 与 c 一起使用 System Diagnostics ProcessStartInfo proccessStartInfo new System Diagnostics ProcessStartInfo n
  • 如何阅读shell命令的源代码?

    我想阅读编写linux命令的实际源代码 我已经获得了一些使用它们的经验 现在我认为是时候与我的机器进行更深层次的交互了 我在这里找到了一些命令http directory fsf org wiki GNU http directory fs
  • execlp 多个“程序”

    我想运行类似的东西 cat file tar base64 myprogram c base64 d tar zvt I use execlp运行该进程 当我尝试运行类似的东西时cat它有效 但如果我尝试运行base64 d tar zvt
  • 类unix系统中的python和python3命令有什么区别?

    我通读了每个命令的描述 但每个命令的描述都是完全相同的 所以我不明白这两个命令在类 Unix 系统中的工作方式有何不同 谁能解释其中的区别吗 Python3命令的引入是因为python命令指向了python2 从那时起 Python3 已成
  • Unix 命令列出包含字符串但*不*包含另一个字符串的文件

    如何递归查看包含一个字符串且不包含另一个字符串的文件列表 另外 我的意思是评估文件的文本 而不是文件名 结论 根据评论 我最终使用了 find name html exec grep lR base maps xargs grep L ba
  • Ruby,通过 SSH 和 LOG 逐一运行 linux 命令

    我想用 Ruby 女巫 net ssh 编写代码 在远程 Linux 机器上一一运行命令并记录所有内容 在 Linux 机器上称为命令 stdout 和 stderr 所以我写函数 def rs ssh cmds cmds each do
  • 左右 mac“命令”键的配置不同吗?

    我想知道是否可以将右侧的 mac 命令 设置为像 ctrl 键一样 但保留左侧 命令 键的默认功能 谢谢 有一个非常棒的应用程序 称为 Ukelele 免费 不幸的是 它无法区分左右命令键 然而 我最近发现了一个更好的应用程序 名为 Con
  • Ruby 在特定目录中运行 shell 命令

    我知道如何在 Ruby 中运行 shell 命令 例如 x cmd 但是 如何指定运行此命令的目录 有没有类似的脱壳方式 类似subprocess Popen在Python中 subprocess Popen r c mytool tool
  • 何时为 WPF/MVVM 使用事件和命令?

    我正在练习如何使用 MVVM 模式编写 WPF 应用程序 到目前为止 我还没有在我的代码中使用命令 在我的视图模型中我实现INotifyPropertyChanged并使用 事件PropertyChangedEventHandler Pro
  • 如何使 Django 自定义管理命令参数不再需要?

    我正在尝试在 django 中编写自定义管理命令 如下所示 class Command BaseCommand def add arguments self parser parser add argument delay type int
  • 如何在 Windows 中的命令提示符启动时运行命令

    EDIT 如果您想在计算机启动时执行任何任务或基于 活动这非常有帮助 http answers microsoft com en us windows forum windows 7 performance how to schedule
  • 从命令行创建 Excel 文件

    有什么方法可以从命令行创建新的 Excel 文件吗 如果您需要创建的 Excel 文件始终相同 您可以手动创建模板 然后随意创建新文件 例如 copy template xlsx myNewSpreadsheet xlsx 如果您需要创建内
  • Android 对 Runtime.getRuntime().exec() 的权限

    我有一个应用程序在清单上具有以下权限 我的应用程序在 Android JB 4 1 2 上运行 UPDATE 我尝试在 JB 上运行该应用程序 但它不起作用 它适用于早期的 API 版本

随机推荐

  • vue2.0生命周期—码虫

    1 下面是我对生命周期的一些理解 首先我们先看一下Vue生命周期图 2 它可以分为八个阶段 钩子函数 函数描述 beforeCreate 组件实例刚被创建 组件属性计算之前 如data属性等 created 组件实例创建完成 属性已绑定 但
  • 播放4K视频需要什么样的配置

    我们知道 相对于标清视频和高清视频 HD 4K视频是一个新的高度 4K分辨率属于超高清分辨率 在此分辨率下 观众将可以看清画面中的每一个细节 每一个特写 影院如果采用4096 2160分辨率 无论在影院的哪个位置 观众都可以清楚地看到画面的
  • 人脸识别引擎SeetaFaceEngine简介及在windows7 vs2013下的编译

    SeetaFaceEngine是开源的C 人脸识别引擎 无需第三方库 它是由中科院计算所山世光老师团队研发 它的License是BSD 2 SeetaFaceEngine库包括三个模块 人脸检测 detection 面部特征点定位 alig
  • cookie、localStorage、sessionStorage区别 == JavaScript中let、const、var 的区别 == es6解构赋值

    cookie localStorage sessionStorage区别 Cookie Cookie设计初衷是用来和服务器通讯 而不是本地存储 他只是被 借用 到本地存储 如下图 每次http请求 header都携带cookie local
  • background-position设置无效问题解决

    2019独角兽企业重金招聘Python工程师标准 gt gt gt html代码部分 div class login div reg1 div
  • Yolov4部署到ZYNQ系列2-重新训练darknet框架下的Yolov4

    文章目录 前言 一 为什么重新训练darknet 二 改进Yolov4结构 1 其他如常 2 修改cfg文件 3 加快运行 三 改进Yolov4结构后的推测效果 总结 前言 花了一个月不到的时间单枪匹马把Yolov4模型部署到ZYNQ Ul
  • 基于Matlab的直方图、Retinex和暗通道图像去雾算法

    基于Matlab的直方图 Retinex和暗通道图像去雾算法 近年来 图像去雾技术在计算机视觉领域得到了广泛关注 由于大气雾霾和环境污染等因素 图像中会存在大量的噪点和雾霭 甚至会导致一些细节无法清晰地呈现 针对这个问题 本文将介绍一种基于
  • Kubernetes 使用 helm 部署 NFS Provisioner

    文章目录 1 介绍 2 预备条件 3 部署 nfs 4 部署 NFS subdir external provisioner 4 1 集群配置 containerd 代理 4 2 配置代理堡垒机通过 kubeconfig 部署 部署 Min
  • 使用python装饰器计算函数运行时间的实例

    使用python装饰器计算函数运行时间的实例 装饰器在python里面有很重要的作用 如果能够熟练使用 将会大大的提高工作效率 今天就来见识一下 python 装饰器 到底是怎么工作的 本文主要是利用python装饰器计算函数运行时间 一些
  • python数据分析实例:利用爬虫获取数据

    我们在工作中用到网络上发布的各种信息 如果用搜索引擎查找并整理 需要花费大量时间 现在python能够帮助我们 使用爬虫技术 提高数据查找和整理的效率 我们来找一个爬虫的案例 抓取求职招聘类网站中的数据 使用环境 win10 python3
  • 一个开源知识管理系统,满足企业定制化需求

    编者按 知识管理是企业加强竞争优势和核心竞争力的保证 开源知识管理系统更是块 香馍馍 本文分析了知识管理系统开源的意义 介绍了开源的知识管理系统 天翎KMS的特点 并进一步阐述了天翎KMS具体实现的功能 概要 1 为什么需要开源知识管理系统
  • C++虚函数表的理解、通过虚函数表访问非public成员函数

    阅读了陈皓老师的虚函数表解析 点击打开链接 以及虚函数表存放位置一文 点击打开链接 对C 如何实现多态应该有了个粗浅认识 1 虚函数表是一个数组 每个元素存储virtual函数的指针 2 如果一个类存在虚函数 编译器一般会将该类实例的前4
  • GJB 软件测试规范

    1 目的及范围 1 1 目的 本规范规定了软件测试的具体实施方法 主要从测试过程和测试管理方面论述 软件测试的目的是验证软件是否满足软件开发合同或任务书 系统 子系统设计文档 软件需求规格说明书和软件设计说明所规定的软件质量特性要求 通过测
  • Large Graph Models: A Perspective

    本文是LLM系列文章 针对 Large Graph Models A Perspective 的翻译 TOC 摘要 大型模型已成为人工智能 尤其是机器学习领域的最新突破性成就 然而 当涉及到图形时 大型模型并没有像在自然语言处理和计算机视觉
  • sqlserver用户登录失败

    问题场景描述 刚使用sql server创建用户后 重新登录时报错说登录失败 解决方案 先使用windows登录 然后进行如下操作
  • 在主函数里面调用fun函数,这样可以吗?

    Int fun Int a 5 Int p a Return p 请问 在主函数里面调用fun函数 这样可以吗 如果不可以 请说明为什么 并给出一种解决方案 a是局部变量 a 的作用域在fun内 p指向a的地址 在return的时候 a的生
  • Node.js学习笔记--fs 文件系统 writeFile函数

    前言 本章学习fs模块中的writeFile函数 即简单文件系统 所谓的简单 其实就是一种封装 把 1 打开文件 2 关闭文件 给封装到方法里面了 这样调用者使用的时候就方便了 1 使用例 先来看一段代码 var fs require fs
  • 【图像识别】基于支持向量机svm植物叶子疾病检测和分类

    最近在学习svm算法 借此文章记录自己的学习过程 在学习很多处借鉴了z老师的讲义和李航的统计 若有不足的地方 请海涵 svm算法通俗的理解在二维上 就是找一分割线把两类分开 问题是如下图三条颜色都可以把点和星划开 但哪条线是最优的呢 这就是
  • java jmap用法_java命令--jmap命令使用

    jdk安装后会自带一些小工具 jmap命令 Java Memory Map 是其中之一 主要用于打印指定Java进程 或核心文件 远程调试服务器 的共享对象内存映射或堆内存细节 jmap命令可以获得运行中的jvm的堆的快照 从而可以离线分析
  • 设计模式6-命令模式(Command)解析+案例实践+总结

    本文是对面向对象设计模式 命令模式 Command 的解析 主要分为定义解析 通过餐厅点餐案例 遥控器案例讲解命令模式 多案例练习加深对命令模式的理解 最后总结知识要点 第一篇 定义解析 命令模式是GoF四人帮整理的 设计模式 可复用面向对