设计模式之命令模式

2023-11-18

        在日常生活中,我们常常会遇到这样一些问题:需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。
        命令模式是非常实用的一个模式,比如最常用的就是我们编写项目中用到的撤销\恢复(Undo\Redo)就是通过命令模式(Command)来实现的;在如我们的计算器、小孩通过遥控器控制赛车运动,这些都是通过命令模式实现的,下面就详细讲解命令模式.

一.模式定义

        命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式.
        在命令模式中发送者与接收者没有直接引用关系,发送请求的对象至需要知道如何发送请求,而不必知道如何完成请求,这就是命令模式的模式动机.

二.模式结构及组成

        命令模式的结构图如下图所示:

        其中命令模式的角色如下所示:
        客户端(Client):创建一个具体的命令对象,并确定其接收者.
        请求者(Invoker):负责发出命令请求.
        接收者(Receiver):具体实施或执行一个请求.
        抽象命令(Command):给出所有具体命令的抽象接口.
        具体命令(ConcreteCommand):实现抽象命令的方法,负责调用接收者.

三.命令模式实例

        先举一个简单的例子:
        1.玉帝下旨让太白金星去招悟空上天庭
        在这个例子中共有五个角色:命令角色:圣旨 ,具体命令角色:具体圣旨,立即上天庭报道,请求者角色:太白金星,接受者角色:美猴王,客户角色:Client玉帝.
        它的模式图如下,这就是一个简单的命令模式的例子.

        下面这个例子是根据清华大学设计模式PPT中摘抄过来的,是一个比较经典的命令模式的例子,在使用遥控器中我们用到的就是命令模式。
        2.电视机遥控器
        电视机是请求的接收者,遥控器是请求的发送者,遥控器上有一些按钮,不同的按钮对应电视机的不同操作。抽象命令角色由一个命令接口来扮演,有三个具体的命令类实现了抽象命令接口,这三个具体命令类分别代表三种操作:打开电视机、关闭电视机和切换频道。显然,电视机遥控器就是一个典型的命令模式应用实例。
        其中:
        接受者--Televison
        请求者--Controller
        抽象命令--AbstractCommand
        具体命令--TCOpenCommand、TVChangeCommand、TVCloseCommand
        其中,在项目中的撤销\恢复(Undo\Redo)也是使用经典的命令模式,这里就简单的给出它的类图,详细的Undo\Redo可见TerryLee的博客,他进行了详细的讲解并有源代码注释:
        请求者可以请求命令执行Display、Undo、Redo的操作队接受者(文章或工程)进行修改。
四.实例代码详解模式
        下面通过股票交易系统的例子和详细代码分析命令模式
        (由于忘记该代码是借鉴了某人的博客,在此处向他表示了对不起,作者只想借鉴你优秀的代码供大家学习,而当初没有记录下你的网址,在此说声抱歉.)
        具体的代码实现如下:
        定义客户端代码,联系请求者、接受者和具体的买卖命令
 
 
        定义股票交易员,请求者
 
         定义抽象命令接口
         定义股票市场,是具体的接受者,执行股票交易操作命令
         定义具体的命令,它继承抽象命令接口,在具体类中定义了具体要执行的函数.
 
五.优缺点
        最后,总结命令模式的优缺点。
        优点:
              1.降低对象之间的耦合度。
              2.新的命令可以很容易地加入到系统中。
              3.可以比较容易地设计一个组合命令。
              4.调用同一方法实现不同的功能
              5.可以用来做批处理操作
              6.Undo\Redo操作
        缺点:
        因为每一个命令都需要设计一个具体命令类,所以可能会导致系统有过多的具体命令类,影响使用。
        最后,我这篇文章主要讲诉的是命令模式,并通过命令模式一些例子来叙述,同时该文章主要思想来自:作者Eastmount自己的思考,《大话设计模式》,《head first设计模式》等书,还有是清华大学的课件,以及一些其他人关于命令模式的博客文章,但由于作者的大意,找不到有些图来自哪?所以如果作者见到,请见谅,我主要是想分享自己的一些知识供大家学习和了解。如果有错误或不足之处,请读者原谅!!!
      (By:Eastmount 2013-5-12-夜2点)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之命令模式 的相关文章

  • 如何在Windows命令提示符下使用单个命令获取java版本?

    我需要获取java版本1 6 0 26从下面java version output java version 1 6 0 26 Java TM SE Runtime Environment build 1 6 0 26 b03 Java H
  • 使用 C# 向 USB 连接的 GPRS 调制解调器发送 AT 命令

    任何人都可以给我一个关于如何访问连接到 USB 端口的 GPRS 调制解调器的良好指示或指南 我应该为我的程序制作一个 USB 驱动程序以将 AT 命令发送到调制解调器吗 或者就像一个路由器 我可以使用IP地址访问它 谢谢 如果 Windo
  • Windows终端:打开多个窗格并执行指定命令

    我最近下载了新的Windows Terminal 我已经创建了用于打开多个窗格的快捷方式 工作正常 但是 我正在尝试为相应的窗格执行命令 wt d
  • 使用shell脚本删除文件夹内容

    我在尝试清空脚本中的文件夹时遇到问题 这在我的命令行中工作 rm r Folder1 Folder2 但如果在我的脚本中我这样做 DIR Folder1 Folder2 rm r DIR 它说 rm Folder1 Folder2 没有这样
  • 我可以通过 DataTrigger (XAML) 调用函数吗?

    我在 xaml cs 中有一个我想调用的函数 xaml cs private void treeView SelectedItemChanged object sender EventArgs e treeView ScrollToCent
  • MVVM 中的命令

    我看过一些教程 人们在他们的代码中创建像 CanExecute 这样的方法 我假设他们这样做是为了帮助读者理解这一切是如何运作的 当我查找 Command 和 ICommand 时 它会将我带到 MSDN 上用于 Windows 应用商店应
  • Matlab:从命令窗口重命名工作区元素?

    Matlab 的 GUI 允许我通过右键单击元素并选择 重命名 选项来重命名工作区中的任何元素 是否也可以从命令窗口执行此操作 这些是您可以轻松亲自测试的事情 并且您应该这样做 这是学习 发现的最佳方式 无论如何 答案是否定的 您不能从命令
  • 如何在 Emacs 中创建目录?

    究竟如何使用 Emacs 创建新目录 我使用什么命令 如果可以的话请举个例子 创建目录dir to create type M x make directory RET dir to create RET 创建目录dir parent1 n
  • 从 UNIX 树中删除路径前缀

    我对 UNIX 命令有一个要求 我有一条与此类似的路径 path to file manyfiles extensions 现在我想要的输出类似于 file manyfiles extensions 现在我可以列出 path to 和 pa
  • Maya Python 中的 cmds.scriptCtx 到底有什么作用?

    我想知道 cmds scriptCtx 命令到底是做什么的 因为我尝试将其直接从 Autodesk 帮助页面复制并粘贴到我的脚本编辑器中 但没有任何反应 以下是 Autodesk 帮助中的脚本 import maya cmds as cmd
  • 如何在 Linux 中创建别名? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 假设我想为 srm 创建一个别名 安全删除 这样每次使用 srm 时 都会运行交互式 rm 命令 例如rm i 需要对必要的配置文件进行此
  • 日期格式到cron格式转换

    我想将日期格式更改为 cron 日期格式 怎么办 日期格式 2018 05 15 17 30 00 cron 格式 30 17 15 05 您可以通过多种方式做到这一点 但这是更简单的方法之一 bin bash DATESTR 2018 0
  • 不读取 awk 命令文件中的文件第一行

    我无法使我的 awk 命令列表无法读取数据文件的第一行 它必须读取除第一行之外的每一行 然后将运动员和年份连接成一个字符串 后来在程序中我使用了数组 我没有列出所有代码 下面列出了数据文件的前两行 我需要让它不读取标题行 而只从第一位运动员
  • Vim:如何将一组行重新格式化为一行(如果该行是一个句子)?

    不是重复的在 Vim 中 将文件中的所有行连接成一行的最简单方法是什么 https stackoverflow com questions 391710 in vim what is the simplest way to join all
  • 奇怪的问题,除非单击鼠标,否则按钮不会重新启用

    我的应用程序是使用 WPF 中的 MVVM 模式编写的 我的所有按钮都使用命令绑定来执行模型中的代码 所有命令在 CanExecute 中都有代码来确定绑定按钮的启用状态 该逻辑工作完美 但在所有情况下 GUI 都会保持禁用状态 除非我单击
  • 当用户控件可见时将焦点设置到它

    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
  • 如何在c#中使用net user

    我正在尝试将 net user 与 c 一起使用 System Diagnostics ProcessStartInfo proccessStartInfo new System Diagnostics ProcessStartInfo n
  • WPF - 从 UserControl 发出命令时 CanExecute 不会触发

    我有一个按钮条用户控件 我想在我的大多数表单上使用它 我添加了如下命令 public ICommand Create get return buttonCreate Command set buttonCreate Command valu
  • 如何使用 wamp 在 Windows 上烘焙 cakephp 2.0 应用程序

    我想在Windows系统上烤蛋糕php项目 我正在使用 wamp 服务器来运行 PHP mysql 我已经浏览过 cakephp 网站上的视频投射 并设置了环境设置 按照演示给出命令 蛋糕 后 最后我收到一条消息说 php 不被识别为内部或
  • MVVM 路由和中继命令

    两者有什么区别路由命令 http msdn microsoft com en us library system windows input routedcommand aspx and 中继命令 http msdn microsoft c

随机推荐

  • Window&linux使用换行符的问题总结

    1 Window使用Git时 设置换行符格式 参见 https www jianshu com p 6ef90ce18ba2 2 vi下设置回车换行符等特殊符号 换行方式 在早期的打印机时代 开始新的一行要占用两个字符的时间 如果到了一行的
  • java.lang.UnsatisfiedLinkError

    java lang UnsatisfiedLinkError 原因 jni注册的时候匹配写错了 I B B 如下 static JNINativeMethod methods native getSps I B B void Native
  • Keras保存模型并载入模型继续训练

    我们以MNIST手写数字识别为例 import numpy as np from keras datasets import mnist from keras utils import np utils from keras models
  • PyQt5中的按钮3-QCommandLinkButton

    PyQt5中的按钮3 QCommandLinkButton QCommandLinkButton介绍 QCommandLinkButton举例 QCommandLinkButton介绍 CommandLinkButton 外观像是一个被设置
  • verilog赋多位值_关于verilog 赋值

    1 wire表示直通 即只要输入有变化 输出马上无条件地反映 reg表示一定要有触发 输出才会反映输入 2 只有 lt 表示非阻塞 给沿触发的寄存器赋值 是阻塞赋值 给电平触发的信号赋值 3 不指定就默认为1位wire类型 专门指定出wir
  • 计算机视觉论文-2021-07-19

    本专栏是计算机视觉方向论文收集积累 时间 2021年7月19日 来源 paper digest 欢迎关注原创公众号 计算机视觉联盟 回复 西瓜书手推笔记 可获取我的机器学习纯手推笔记 直达笔记地址 机器学习手推笔记 GitHub地址 1 T
  • 在struts1.1框架下,利用smartupload实现文件的上传(可以是多个文件)

    1 前端页面upload jsp 后台处理程序UplodAction java 2 struts config的配置参数如下 没有设置 ActionForm
  • JAVA的WebService规范(支持)

    SOA Service Oriented Architecture 面向服务架构是一种思想 它将应用程序的不同功能单元通过中立的契约 独立于硬件平台 操作系统和编程语言 联系起来 使得各种形式的功能单元更好的集成 目前来说 WebServi
  • windows7旗舰版 appium环境搭建

    1 安装jdk 8u171 windows x64 exe 注意配置环境变量 参考资料 https jingyan baidu com article 6dad5075d1dc40a123e36ea3 html java version 查
  • Modbus RTU协议各知识点入门 + 实例

    文章目录 1 起因 2 几个重点 2 1 一些难懂的概念 2 2 CRC的高低位 2 3 其他 3 介绍 3 1 起源 3 2 分类 4 格式 4 1 串口协议 4 2 帧格式 5 数据类型 6 功能码 7 CRC16 modbus 8 实
  • React(Hook介绍)

    为什么要用Hook 介绍Hooks之前 首先要给大家说一下React的组件创建方式 一种是类组件 一种是纯函数组件 并且React团队希望 组件不要变成复杂的容器 最好只是数据流的管道 开发者根据需要 组合管道即可 也就是说组件的最佳写法应
  • 如何在 CentOS 8 上安装 Python 3.8

    本文来自于 阿里云官方镜像站 https developer aliyun com mirror utm content g 1000307095 原文链接 https developer aliyun com article 756221
  • 报错java.lang.Long cannot be cast to java.lang.Integer解析

    用博客记录工作中出现的问题 给自己一个提醒 也给其他朋友一些借鉴 报错 java lang Long cannot be cast to java lang Integer Long 无法转化成Integer类型 这个异常 经常出现在hin
  • 正确理解Widget::Widget(QWidget *parent) :QWidget(parent)这句话

    该如何理解下面段代码的第二行QWidget parent 1 Widget Widget QWidget parent 2 QWidget parent 3 4 在讲解原因之前 先请大家看下面的一个例子 include
  • git切换分支时报错(error: pathspec ‘master‘ did not match any file(s) known to git.)的解决方法

    git切换分支时报错 切换分支 root git my code git checkout master 产生如下报错 error pathspec master did not match any file s known to git
  • 用 Python 爬取网红城市大长沙!

    这两天获取了两份关于长沙的数据 长沙景点和长沙美食 之后进行了分析 如果有朋友想去长沙或者周边城市玩 要仔细看看喔 导入库 长沙景点 数据获取 长沙景点的数据获取方法和之前那篇关于厦门的文章是一样的 只是重新跑了一遍代码 具体过程不再阐述
  • HADOOP集群搭建

    安装步骤 机器mini yum mini2 mini3 mini4 注意 下面的步骤在4台机子上都要做的操作 1先将虚拟机的网络模式选为NAT 2修改主机名 vi etc sysconfig network NETWORKING yes H
  • git:kex_exchange_identification:Connection closed by 52.74.223.119 port 22

    使用Rider的git进行push操作时提示 kex exchange identification Connection closed by remote host Connection closed by 52 74 223 119 p
  • AJAX 缓存处理

    关于AJAX请求服务器后缓存数据 造成没有及时刷新的问题 最近在做项目的时候 使用了ajax去请求服务器的数据 刚开始还可以 我测试一切运行正常 我不是专业的测试人员哈 所以还是有些问题没有测出来哈 后来ajax请求的数据变化了 但是页面数
  • 设计模式之命令模式

    在日常生活中 我们常常会遇到这样一些问题 需要向某些对象发送请求 但是并不知道请求的接收者是谁 也不知道被请求的操作是哪个 我们只需在程序运行时指定具体的请求接收者即可 此时 可以使用命令模式来进行设计 使得请求发送者与请求接收者消除彼此之