【设计模式】Java 设计模式之模板命令模式(Command)

命令模式(Command)的深入分析与实战解读

一、概述
命令模式是一种将请求封装为对象从而使你可用不同的请求把客户端与接受请求的对象解耦的模式。在命令模式中,命令对象使得发送者与接收者之间解耦,发送者通过命令对象来执行请求,而接收者则执行命令对象的操作。

二、模式结构
命令模式主要包含四个角色:

  1. 抽象命令类(Command):声明执行操作的接口。
  2. 具体命令类(ConcreteCommand):实现抽象命令接口的具体命令类,它持有接收者对象,并调用接收者的相应操作以执行请求。
  3. 接收者类(Receiver):执行具体操作的类。
  4. 调用者类(Invoker):要求命令对象执行请求。

三、实现方式
命令模式的实现可以通过接口或抽象类来定义命令的行为,具体命令类实现这些行为,并持有对接收者的引用。调用者通过命令对象来调用接收者的方法,而无需直接知道接收者的具体类型。

在这里插入图片描述
直接请求,依赖关系太强。Handler类的改变,需要修改ListView。
通过增加Command抽象命令类,将不符合抽象编程的handler 调用,转为抽象编程。在这里插入图片描述

四、代码示例

// 抽象命令类
public interface Command {void execute();
}// 具体命令类
public class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.action();}
}// 接收者类
public class Receiver {public void action() {System.out.println("Receiver action performed.");}
}// 调用者类
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {command.execute();}
}

五、优点

  1. 解耦:命令模式将请求与具体实现解耦,使得调用者与接收者之间不再直接依赖。
  2. 灵活性和扩展性:可以很容易地添加新的命令类型,无需修改现有代码。
  3. 可撤销和恢复:可以在命令对象中实现撤销和恢复操作。

六、缺点

  1. 可能产生过多具体命令类:对于每一个请求都可能需要一个具体命令类,导致系统复杂性增加。
  2. 可能不适合所有情况:在一些简单场景下,引入命令模式可能增加不必要的复杂性。

七、应用场景

  1. GUI应用:如按钮点击事件处理,每个按钮对应一个命令对象。
  2. 事务处理:将事务封装为命令对象,便于管理事务的执行和撤销。
  3. 日志记录:将日志记录操作封装为命令对象,便于灵活配置日志记录行为。

八、实战解读
以GUI应用为例,假设有一个“撤销”按钮,用户点击该按钮时希望撤销上一步的操作。通过命令模式,可以将每个操作封装为一个命令对象,并维护一个命令历史栈。当用户点击“撤销”按钮时,从栈中弹出最后一个命令并执行其撤销操作。

九、注意事项
在使用命令模式时,需要注意避免过度使用,以免增加不必要的复杂性。同时,要确保命令对象的执行和撤销操作是安全的,不会导致系统状态不一致或数据损坏。

十、命令模式的可维护性
命令模式使得请求的处理逻辑可以被封装和复用,这大大提高了系统的可维护性。当需要修改某个操作的行为时,只需修改相应的命令类,而无需影响其他部分的代码。

十一、命令队列和宏命令
命令模式支持将多个命令组合成一个命令队列或宏命令,从而一次性执行多个操作。这为用户提供了更高级别的操作灵活性,并简化了复杂操作的执行过程。

十二、命令模式与策略模式的关系
命令模式与策略模式在某种程度上具有相似性,都涉及到行为的封装和替换。然而,命令模式更侧重于请求的处理和封装,而策略模式则更侧重于算法的封装和替换。在实际应用中,可以根据具体需求选择使用哪种模式。

十三、命令模式的线程安全性
在多线程环境中,命令模式可以确保每个命令对象的执行是线程安全的。通过将命令对象设计为无状态的,可以避免多线程间的数据竞争和状态不一致问题。

十四、命令模式的扩展性
命令模式具有良好的扩展性,可以通过添加新的命令类来扩展系统的功能。这使得系统在面对新的需求或变更时能够更加灵活地应对,降低了系统的维护成本。

综上所述,命令模式不仅提高了系统的可维护性和可扩展性,还为多线程环境下的请求处理提供了线程安全的保障。同时,它与策略模式等其他设计模式相互配合,可以构建出更加灵活和健壮的系统架构。

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

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

相关文章

AI预测福彩3D第15弹【2024年3月21日预测--第3套算法重新开始计算第4次测试】

今天咱们继续对第3套算法进行第4次测试,第3套算法加入了012路的权重。废话不多说了,直接上结果吧~ 最终,经过研判分析,2024年3月21日福彩3D的七码预测结果如下: 百位:4 5 7 1 0 6 2 十位:3 1 5 …

森工新材料诚邀您参观2024杭州快递物流展会

2024杭州快递物流供应链与技术装备展览会 2024.7.8-10 杭州国际博览中心 参展企业介绍 深圳森工新材料科技有限公司。该公司致力于对传统包装材料的环保升级与替代,产品已广泛应用于日用消费品、工业生产、农业种植及医疗卫生领域。降解产品于2020年已入选国家邮政…

MySQL | 事务

目录 1. 前言 2. 什么是事务? 3. 为什么出现事物? 4. 事物的版本支持 4.1. 事务提交方式 5. 事务常见操作方式 6. 事务隔离级别 6.1. 隔离级别 6.2. 查看与设置隔离性 6.2.1. 查看 6.2.2. 设置 6.3. 读未提交[Read Uncommitted] 6.4. 读提交…

uniapp安装axios

先npm安装 npm i axios然后在项目里面建一个utils文件,再建一个index.js 以下是index.js代码: import axios from axios; const service axios.create({baseURL: //xxxx.xxxxx.com///你的请求接口域名, timeout: 6000, // request timeoutcrossDomai…

IPC网络摄像头媒体视屏流MI_VIF结构体

一个典型的IPC数据流 下图是一个典型的IPC数据流模型,流动过程如下: 1. 建立Vif->Vpe->Venc的绑定关系; 2. Sensor 将数据送入vif处理; 3. Vif 将处理后的数据写入Output Port申请的内存,送入下一级;…

ARM32day4

VID_20240319_210515 1.思维导图 2.实现三个LED灯亮灭 .text .global _start _start: 使能GPIO外设时钟 LDR R0,0x50000A28 LDR R1,[R0]使能GPIOE ORR R1,R1,#(0X1<<4)使能GPIOF ORR R1,R1,#(0X1<<5) STR R1,[R0]设置引脚状态 LDR R0,0X50006000 LDR R1,[R0…

34 vue 项目默认暴露出去的 public 文件夹 和 CopyWebpackPlugin

前言 这里说一下 vue.config.js 中的一些 public 文件夹是怎么暴露出去的? 我们常见的 CopyWebpackPlugin 是怎么工作的 ? 这个 也是需要 一点一点积累的, 因为 各种插件 有很多, 不过 我们仅仅需要 明白常见的这些事干什么的即可 当然 以下内容会涉及到一部分vue-cli,…

MySQL 更新执行的过程

优质博文&#xff1a;IT-BLOG-CN Select语句的执行过程会经过连接器、分析器、优化器、执行器、存储引擎&#xff0c;同样的 Update语句也会同样走一遍 Select语句的执行过程。 但是和 Select最大不同的是&#xff0c;Update语句会涉及到两个日志的操作redo log&#xff08;重做…

MySQL面试题--MySQL内部技术架构

目录 1.Mysql内部支持缓存查询吗&#xff1f; 2.MySQL8为何废弃掉查询缓存&#xff1f; 3.替代方案是什么&#xff1f; 4.Mysql内部有哪些核心模块组成&#xff0c;作用是什么&#xff1f; 5.一条sql发送给mysql后&#xff0c;内部是如何执行的&#xff1f;&#xff08;说…

【计算机网络篇】数据链路层(2)封装成帧和透明传输

文章目录 &#x1f95a;封装成帧和透明传输&#x1f388;封装成帧&#x1f388;透明传输&#x1f5d2;️面向字节的物理链路使用字节填充的方法实现透明传输。&#x1f5d2;️面向比特的物理链路使用比特填充的方法实现透明传输。 &#x1f6f8;练习 &#x1f95a;封装成帧和透…

Zabbix与Prometheus区别简述

Zabbix与Prometheus区别简述 历史沿革 一、监控工具简介 1、Zabbix https://www.zabbix.com/cn/download Zabbix是传统的监控系统&#xff0c;出现比云原生早&#xff0c;使用的是SQL关系型数据库&#xff1b;开源监控软件&#xff0c;遵守 GPLv2开源协议&#xff0c;起源于…

Aztec的客户端证明

1. 引言 隐私保护 zk-rollup 的证明生成与通用 zk-rollup 的证明生成有很大不同。原因是给定交易中存在特定数据&#xff08;由私有函数处理&#xff09;&#xff0c;我们希望保持完全私有。在本文中&#xff0c;我们探讨了用于证明私有函数正确执行的客户端证明生成&#xff…

QB 返回的数据格式

想要的效果: 而不是 $a[pm] [pm ,cover,power] 这种形式.对应的方法! public function withAttr($name, callable $callback null){if (is_array($name)) {foreach ($name as $key > $val) {$this->withAttr($key, $val);}return $this;}$this->options[with_attr…

web前端之小功能聚集、简单交互效果

MENU 纯CSS实现可编辑文字霓虹灯闪烁效果css之实现流水文字、闪烁、荧光、炫酷web前端之文本擦除效果与下划线结合css之下划线动画 纯CSS实现可编辑文字霓虹灯闪烁效果 效果图 html <h1 contenteditable"true">Hello World</h1>style * {margin: 0;pa…

【Flink】Flink 中的时间和窗口之窗口其他API的使用

1. 窗口的其他API简介 对于一个窗口算子而言&#xff0c;窗口分配器和窗口函数是必不可少的。除此之外&#xff0c;Flink 还提供了其他一些可选的 API&#xff0c;可以更加灵活地控制窗口行为。 1.1 触发器&#xff08;Trigger&#xff09; 触发器主要是用来控制窗口什么时候…

微服务高级篇(三):分布式缓存+Redis集群

文章目录 一、单点Redis的问题及解决方案二、Redis持久化2.1 单机安装Redis2.2 RDB持久化2.3 AOF持久化2.4 RDB和AOF对比 三、Redis主从3.1 搭建Redis主从架构3.1.1 集群结构3.1.2 准备实例和配置3.1.3 启动3.1.4 开启主从关系3.1.5 测试 3.2 数据同步3.2.1 全量同步【建立连接…

idea import的maven类报红

idea 报红/显示红色的原因 一般报红&#xff0c;显示红色&#xff0c;是因为 idea 在此路径下&#xff0c;找不到这个类。 找到是哪个 jar 包的类导致 idea 报红 点击报红的路径的上一层&#xff0c;进入jar 包。比如&#xff1a; import com.aaa.bbb.ccc.DddDto;这个 impo…

<c语言学习>结构体

结构体类型 为什么要有结构体 我们用c语言描述年龄时候&#xff0c;可以定义一个整形类型来实现&#xff1a; int age; age 18; printf("年龄为%d",age); (c语言描述年龄) 由于年龄这一属性比较单一&#xff0c;类似性别、某游戏角色攻击力、血量都可以用c语言内置…

亚马逊AWS展示高效纠错的全新量子比特!

亚马逊网络服务公司&#xff08;AWS&#xff09;在量子计算的纠错技术领域取得了显著成就&#xff0c;极大地简化了量子系统的复杂性和资源需求。他们的研究人员通过采用“双轨擦除”量子比特&#xff08;dual-rail erasure qubit&#xff09;技术&#xff0c;有效地克服了量子…

Flink入门知识点汇总(二)

具体内容请看b站尚硅谷课程&#xff01; 32_Flink运行时架构_提交流程_Yarn应用模式_哔哩哔哩_bilibili 窗口 Flink的窗口并不是静态准备好的&#xff0c;而是动态创建的。数据流到达时不会准备24个或者其他完整数量的桶&#xff0c;而是当下桶接满了&#xff0c;才临时又拿新…