热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

16、设计模式行为型模式命令模式

命令模式(请求发送者与接收者解耦)在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法)&#

命令模式(请求发送者与接收者解耦)

 

在软件开发中,我们经常需要向某些对象发送请求(调用其中的某个或某些方法),但是并
不知道请求的接收者是谁,也不知道被请求的操作是哪个,此时,我们特别希望能够以一种
松耦合的方式来设计软件,使得请求发送者与请求接收者能够消除彼此之间的耦合,让对象
之间的调用关系更加灵活,可以灵活地指定请求接收者以及被请求的操作。命令模式为此类
问题提供了一个较为完美的解决方案

 

命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发
送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

 

定义:

将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化

对请求排队或者记录请求日志,以及支持可撤销的操作。

命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。

 

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

 

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

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

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

Receiver(接收者):接收者执行与请求相关的操作,它具体实现对请求的业务处理。

 

命令模式的本质是对请求进行封装,一个请求对应于一个命令,将发出命令的责任和执行命
令的责任分割开。每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收
的一方收到请求,并执行相应的操作

 

命令模式允许请求的一方和接收的一方独立开来,使
得请求的一方不必知道接收请求的一方的接口,更不必知道请求如何被接收、操作是否被执
行、何时被执行,以及是怎么被执行的。

 

命令模式的关键在于引入了抽象命令类,请求发送者针对抽象命令类编程,只有实现了抽象
命令类的具体命令才与请求接收者相关联。

 

事例:

抽象命令类

abstract class Command {public abstract void execute();
}

 

具体命令类

public class MinimizeCommand extends Command {private WindowHanlder whObj; //维持对请求接收者的引用public MinimizeCommand() {whObj = new WindowHanlder();}//命令执行方法,将调用请求接收者的业务方法public void execute() {whObj.minimize();}
}

public class HelpCommand extends Command {private HelpHandler hhObj; //维持对请求接收者的引用public HelpCommand() {hhObj = new HelpHandler();}//命令执行方法,将调用请求接收者的业务方法public void execute() {hhObj.display();}
}

 

接收者

帮助文档处理类

public class HelpHandler {public void display() {System.out.println("显示帮助文档!");}}

 

 窗口处理类

public class WindowHanlder {public void minimize() {System.out.println("将窗口最小化至托盘!");}}

 

请求发送者

public class FunctionButton {private String name; //功能键名称private Command command; //维持一个抽象命令对象的引用public FunctionButton(String name) {this.name = name;}public String getName() {return this.name;}//为功能键注入命令public void setCommand(Command command) {this.command = command;}//发送请求的方法public void onClick() {System.out.print("点击功能键:");command.execute();}
}

 

功能键设置窗口类

public class FBSettingWindow {private String title; //窗口标题//定义一个ArrayList来存储所有功能键private ArrayList functionButtons = new ArrayList();public FBSettingWindow(String title) {this.title = title;}public void setTitle(String title) {this.title = title;}public String getTitle() {return this.title;}public void addFunctionButton(FunctionButton fb) {functionButtons.add(fb);}public void removeFunctionButton(FunctionButton fb) {functionButtons.remove(fb);}//显示窗口及功能键public void display() {System.out.println("显示窗口:" + this.title);System.out.println("显示功能键:");for (Object obj : functionButtons) {System.out.println(((FunctionButton)obj).getName());}System.out.println("------------------------------");}}

public class client {public static void main(String[] args) {FBSettingWindow fbsw = new FBSettingWindow("功能键设置");FunctionButton fb1,fb2;fb1 = new FunctionButton("功能键1");fb2 = new FunctionButton("功能键1");Command command1,command2;//通过读取配置文件和反射生成具体命令对象command1 = new HelpCommand();command2 = new MinimizeCommand();//将命令对象注入功能键
fb1.setCommand(command1);fb2.setCommand(command2);fbsw.addFunctionButton(fb1);fbsw.addFunctionButton(fb2);fbsw.display();//调用功能键的业务方法
fb1.onClick();fb2.onClick();}}

 图构:

 

优点:

(1) 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间
实现完全解耦,相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的
请求者使用,两者之间具有良好的独立性。


(2) 新的命令可以很容易地加入到系统中。由于增加新的具体命令类不会影响到其他类,因此
增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的
要求。


(3) 可以比较容易地设计一个命令队列或宏命令(组合命令)。


(4) 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。

 

 缺点:

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

 

 适用场景

(1) 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者
无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。


(2) 系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调
用者可以有不同的生命期,换言之,最初的请求发出者可能已经不在了,而命令对象本身仍
然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可
以通过请求日志文件等机制来具体实现。


(3) 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。


(4) 系统需要将一组操作组合在一起形成宏命令。

 


转载于:https://www.cnblogs.com/Mrchengs/p/10899245.html


推荐阅读
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • JavaScript和HTML之间的交互是经由过程事宜完成的。事宜:文档或浏览器窗口中发作的一些特定的交互霎时。能够运用侦听器(或处置惩罚递次来预订事宜),以便事宜发作时实行相应的 ... [详细]
  • 本文详细介绍了PHP中与URL处理相关的三个函数:http_build_query、parse_str和查询字符串的解析。通过示例和语法说明,讲解了这些函数的使用方法和作用,帮助读者更好地理解和应用。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文介绍了Linux Shell中括号和整数扩展的使用方法,包括命令组、命令替换、初始化数组以及算术表达式和逻辑判断的相关内容。括号中的命令将会在新开的子shell中顺序执行,括号中的变量不能被脚本余下的部分使用。命令替换可以用于将命令的标准输出作为另一个命令的输入。括号中的运算符和表达式符合C语言运算规则,可以用在整数扩展中进行算术计算和逻辑判断。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有