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

news2024/11/15 17:57:56

1、简介

1.1、概述

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

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

1.2、定义

将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。

2、解析

2.1、UML类图

命令模式的核心在于引入了命令类。通过命令类来降低发送者和接收者的耦合度,请求发送者只需指定一个命令对象,再通过命令对象来调用请求接收者的处理方法,其结构如下图所示:
在这里插入图片描述
可以看出,在命令模式结构图中包含以下4个角色:

  1. Command(抽象命令类):抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的execute()等方法,通过这些方法可以调用请求接收者的相关操作。
  2. ConcreteCommand(具体命令类):具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法。它对应具体的接收者对象,将接收者对象的动作绑定其中。在实现execute()方法时,将调用接收者对象的相关操作(Action)。
  3. Invoker(调用者):调用者即请求发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接收者的相关操作。
  4. Receiver(接收者):接收者执行与请求相关的操作,它具体实现对请求的业务处理。

2.2、代码示例

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

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

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

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

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

class Invoker{
   private Command command;
   // 构造注入
   public Invoker(Command command){
       this.commond=commond;
   }
   
   // 设值注入
   public void setCommand(Command command){
       this.commond=commond;
   }
  
   // 业务方法,用于调用命令类的execute()方法
   public void call(){
      command.execute();
   }
}

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

class ConcreteCommand extends Commond{
    // 维持一个对请求接受者对象的引用
    private Receiver receiver=new Receiver();

    // 调用请求接受这的业务方法action()
    public void execute(){
        receiver.action();
    }
}

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

class Receiver{
   public void action(){
      // 具体操作
   }
}

3、宏命令

宏命令(Macro Command)又称为组合命令,它是组合模式和命令模式联用的产物。宏命令是一个具体命令类,它拥有一个集合属性,在该集合中包含了对其他命令对象的引用。通常宏命令不直接与请求接收者交互,而是通过它的成员来调用接收者的方法。当调用宏命令的execute()方法时,将递归调用它所包含的每个成员命令的execute()方法。一个宏命令的成员可以是简单命令,还可以继续是宏命令。执行一个宏命令将触发多个具体命令的执行,从而实现对命令的批处理。其结构如下图所示:
在这里插入图片描述

4、命令模式总结

命令模式是一种使用频率非常高的设计模式,用于将请求发送者与接收者解耦。请求发送者通过命令对象来间接引用请求接收者,使得系统具有更好的灵活性和可扩展性。在基于GUI的软件开发,无论是计算机桌面应用还是移动应用中命令模式都得以广泛应用。

4.1、主要优点

  1. 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者。同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
  2. 新的命令可以很容易地加入系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码甚至客户类代码,满足开闭原则的要求。
  3. 可以比较容易地设计一个命令队列或宏命令(组合命令)。
  4. 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。

4.2、主要缺点

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

4.3、适用场景

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。
  2. 系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以有不同的生命期。换言之,最初的请求发出者可能已经不在了,而命令对象本身仍然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可以通过请求日志文件等机制来具体实现。
  3. 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
  4. 系统需要将一组操作组合在一起形成宏命令。

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

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

相关文章

LaTex的下载与安装超详细windows版

1.LaTex的下载 (texlive下载TexStudio下载) (1)texlive下载: 这里清华镜像下载 (2)TexStudio下载: 点这里下载镜像 可以根据不同的系统选择不同的版本 2 .LaTex的安装 &#…

1分钟解决github push/pull报错443

1.打开https://www.ipaddress.com/ 2.复制如图IP地址 3.文件夹打开C:\Windows\System32\drivers\etc,复制hosts文件,粘贴到桌面 4.在桌面用记事本打开复制过来的hosts 5.在末尾加上一行,IP写刚才复制的 6.复制桌面的hosts,粘贴回C:\Window…

web开发中的安全和防御入门——csp (content-security-policy内容安全策略)

偶然碰到iframe跨域加载被拒绝的问题,原因是父页面默认不允许加载跨域的子页面,也就是的content-security-policy中没有设置允许跨域加载。 简单地说,content-security-policy能限制页面允许和不允许加载的所有资源,常见的包括&a…

3DEXPERIENCE用户角色 | Structural Performance Engineer 结构性能工程师

- 3DEXPERIENCE 用户角色 - 快速、真实和准确的仿真 推动产品工程创新并促进协作 通过 Structural Performance Engineer,您可以在基于云的 3DEXPERIENCE 平台上执行结构静态、频率、扭曲、模态动态响应,以及零件和装配体结构热仿真。 亮点 与 SOLIDW…

统一观测|借助 Prometheus 监控 ClickHouse 数据库

引言 ClickHouse 作为用于联机分析(OLAP)的列式数据库管理系统(DBMS), 最核心的特点是极致压缩率和极速查询性能。同时,ClickHouse 支持 SQL 查询,在基于大宽表的聚合分析查询场景下展现出优异的性能。因此,获得了广泛的应用。本文旨在分享阿…

【Golang】基于录制,自动生成go test接口自动化用例

目录 背景 框架 ginkgo初始化 抓包&运行脚本 目录说明 ∮./business ∮./conf ∮./utils ∮./testcase testcase 用例目录结构规则 示例 实现思路 解析Har数据 定义结构体 解析到json 转换请求数据 转换请求 转换请求参数 写业务请求数据 写gotest测试…

K8s总结

K8s 是什么 Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的机制…

【从零开始学习JAVA | 第三十五篇】IO流综合练习

目录 前言: 1.拷贝文件(含子文件) 思路: 2.文件加密 思路: 3.修改文件中的数据: 思路: 总结: 前言: 在前面我们为大家介绍了FILE类和IO类。这篇文章我们来练习一…

SQL SERVER 中将数据表中的字段按分隔符分成多行多列

SQL SERVER 中将数据表中的字段按分隔符分成多行多列_sql按逗号拆分列为多行_帅气的苹果果的博客-CSDN博客 SELECTa.name,monitors SUBSTRING ( a.monitors, b.number, charindex( ,, a.monitors ,, b.number ) - b.number ) FROM( SELECT name, monitors FROM [dbo].[ssm_vi…

Packet Tracer - 连接有线和无线 LAN

Packet Tracer - 连接有线和无线 LAN 地址分配表 设备 接口 IP 地址 连接到 云 Eth6 N/A Fa0/0 Coax7 N/A Port0 电缆调制解调器 Port0 N/A Coax7 Port1 N/A 互联网 Router0 控制台端口 N/A RS232 Fa0/0 192.168.2.1/24 Eth6 Fa0/1 10.0.0.1/24 Fa…

安科瑞智能照明系统在医院智能建筑中应用的优势

摘要:现阶段,我国的社会经济的发展水平不断提高,为智能照明系统的发展带来了新的契机。文章主要介绍了几类智能照明系统,分析了其优点,并介绍了智能照明系统在医院建筑中的具体应用,具有一定的参考价值。 …

屏幕取色器Mac版_苹果屏幕取色工具_屏幕取色器工具

Sip for Mac 是Mac系统平台上的一款老牌的颜色拾取工具,是设计师和前端开发工作者必不可少的屏幕取色软件,你只需要用鼠标点一下即可轻松地对屏幕上的任何颜色进行采样和编码,并将颜色数据自动存到剪切板,方便随时粘贴出来。 Sip…

Linux|ubuntu下运行python

参考:ubuntu系统下切换python版本的方法 文章目录 python版本问题查看ubuntu下的所有python版本通过apt-get install可以安装不同版本python查看python版本号更新update-alternatives替代列表查看update-alternatives下的python版本切换python版本删除python版本 p…

Windows7+内网, 安装高版本nodejs,使用vite+vue3+typescript开发项目

前言:vite只支持高版本的nodejs,而高版本的nodejs只支持windows8及以上,且vite还对浏览器版本有兼容问题。以下均为vite官网截图 1、安装好低版本的nodejs win7系统建议安装13.及以下,我的是12.12.0这个版本。nodejs低版本官网下载…

20- C++ STL标准模板库-8 (C++)

第十章 10.1 基本概念 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。现然主要出现在C中,但在被引入C之前该技术就已经存在了很长的一段时间。 STL的从广义上讲分为三类:algorithm&#xff0…

【NLP初级概念】 01-稀疏文档表示(第 1/30 部分)

一、介绍 自然语言处理(NLP)是计算方法的应用,不仅可以从文本中提取信息,还可以在其上对不同的应用程序进行建模。所有基于语言的文本都有系统的结构或规则,通常被称为形态学,例如“跳跃”的过去时总是“跳跃”。对于人类来说,这种形态学的理解是显而易见的。 在这篇介…

kafka总结

Kafka是一种高吞吐量的分布式发布订阅消息系统(消息引擎系统),它可以处理消费者在网站中的所有动作流数据。 消息队列应用场景 缓存/削峰 :处理突然激增的大量数据,先放入消息队列,再按照速度去处理, 解…

技术等级 TRL 定义

“不同环境、不同目标下TRL表述不一样” 技术等级 TRL 定义 TRL1 基本原理提出和发现 TRL2 技术应用研究 TRL3 完成概念验证,如叶栅试验、燃烧室头部试验等 TRL4 完成模拟部件试验.如压气机性能试验,燃烧室扇形试验 TRL5 完…

3ds MAX 绘制喷泉

首先绘制一个小圆柱体当做喷头: 在粒子系统内选择【超级喷射】,并设置对应的参数: 轴和平面的扩散代表了我们看到的水柱能占据多大的面积 另外比较重要的参数是粒子运动和粒子计时 前者是粒子移动的时间也就是喷射的速度 后者代表了喷射出的…

渗透测试:Linux提权精讲(三)之sudo方法第三期

目录 写在开头 sudo jjs sudo journalctl sudo knife sudo less sudo man sudo more sudo mount sudo mysql sudo nano sudo neofetch sudo nice sudo nmap sudo node sudo nohup sudo openvpn sudo passwd sudo perl sudo php sudo pico sudo pkexec su…