Spring框架之命令模式 (Command Pattern)

命令模式(Command Pattern)详解

命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而使你可以用不同的请求对客户端进行参数化;对请求排队或记录日志,以及支持可撤销的操作。命令模式的核心思想是将请求的调用者与执行者解耦,使得请求发送者与请求处理者彼此独立。

1. 命令模式的定义

1.1 什么是命令模式?

命令模式是将请求封装成独立的命令对象,使得请求的发送者和请求的接收者完全解耦。每一个命令对象都实现一个统一的接口,并定义具体的执行操作。请求的发送者只需要知道如何调用命令对象,而不需要了解请求是如何被接收和执行的。

1.2 命令模式的关键思想
  • 解耦请求的发送者和执行者:将操作的请求封装成一个命令对象,由命令对象执行具体的操作。
  • 支持操作的撤销和恢复:通过记录命令的执行历史,可以实现操作的撤销和恢复功能。
  • 易于扩展:新增命令只需扩展新的命令类,无需修改现有代码,符合开闭原则。

2. 命令模式的结构

命令模式通常由以下几个角色组成:

  1. Command(命令接口):定义了一个统一的接口,声明了 execute() 方法,用于执行具体的操作。
  2. ConcreteCommand(具体命令类):实现 Command 接口,并持有对 Receiver(接收者对象)的引用。在 execute() 方法中调用接收者的相关操作。
  3. Receiver(接收者):真正执行命令的对象,命令将请求传递给接收者执行。
  4. Invoker(调用者):请求的发送者,通过调用命令对象的 execute() 方法来执行命令。
  5. Client(客户端):创建具体的命令对象,并将其关联到接收者。然后将命令对象传递给调用者。
类图
Client|
Invoker|
Command Interface|
ConcreteCommand|
Receiver

3. 命令模式的实现

为了更好地理解命令模式,我们来看一个实际的示例。假设我们在开发一个遥控器应用程序,它可以控制电灯的开关操作。我们希望使用命令模式来设计该应用程序,以便支持电灯的开和关操作。

3.1 Java 示例代码
// 1. 命令接口
interface Command {void execute();void undo(); // 支持撤销操作
}// 2. 接收者
class Light {public void turnOn() {System.out.println("灯已打开");}public void turnOff() {System.out.println("灯已关闭");}
}// 3. 具体命令类 - 打开灯
class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOn();}@Overridepublic void undo() {light.turnOff(); // 撤销时关闭灯}
}// 4. 具体命令类 - 关闭灯
class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOff();}@Overridepublic void undo() {light.turnOn(); // 撤销时打开灯}
}// 5. 调用者 - 遥控器
class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}public void pressUndo() {command.undo();}
}// 6. 客户端代码
public class CommandPatternDemo {public static void main(String[] args) {// 创建接收者Light light = new Light();// 创建具体命令对象Command lightOnCommand = new LightOnCommand(light);Command lightOffCommand = new LightOffCommand(light);// 创建调用者RemoteControl remote = new RemoteControl();// 打开灯操作remote.setCommand(lightOnCommand);remote.pressButton(); // 输出: 灯已打开remote.pressUndo();   // 输出: 灯已关闭// 关闭灯操作remote.setCommand(lightOffCommand);remote.pressButton(); // 输出: 灯已关闭remote.pressUndo();   // 输出: 灯已打开}
}

输出结果

灯已打开
灯已关闭
灯已关闭
灯已打开

4. 命令模式的应用场景

命令模式适用于以下场景:

  1. 需要对操作进行记录、撤销、重做:比如文本编辑器的撤销和恢复功能。
  2. 需要参数化方法调用:可以将方法调用封装成命令对象,通过不同的参数传递到调用者。
  3. 需要将行为记录到日志:命令模式可以记录执行的命令以供稍后重放或日志分析。
  4. 支持宏命令(Macro Command):将多个命令组合成一个命令,使得调用者只需要执行一个命令就能触发一系列操作。
  5. 解耦请求发送者和接收者:通过引入命令对象,发送者只需要知道命令接口而不需要知道具体实现。

5. 命令模式的优缺点

5.1 优点
  • 降低系统耦合度:请求的发送者与接收者解耦,方便请求的扩展和变化。
  • 支持撤销和恢复操作:通过引入 undo() 方法,可以轻松实现操作的撤销和恢复功能。
  • 扩展性强:新增命令时,只需要添加新的命令类,而不需要修改现有的系统代码,符合开闭原则。
  • 易于组合命令:可以将多个命令组合成一个宏命令,支持更复杂的操作。
5.2 缺点
  • 增加系统复杂度:引入大量的命令类会增加系统的复杂度,尤其是在命令种类繁多的情况下。
  • 可能导致过多的类:每个操作都需要定义一个新的命令类,当命令数量很多时,会导致系统中类的数量增加,管理起来较为困难。

6. 命令模式的实际应用

命令模式在实际开发中应用非常广泛,特别是在需要对操作进行封装、撤销和重做的场景中。以下是一些常见的应用场景:

  1. 图形用户界面(GUI)按钮操作:将按钮的点击操作封装成命令对象,便于管理和扩展。
  2. 任务调度系统:将任务封装成命令对象,可以轻松实现任务的排队、延迟执行等功能。
  3. 事务处理系统:数据库事务可以使用命令模式来实现,便于事务的回滚和恢复。
  4. 宏命令模式:在游戏开发中,可以使用命令模式记录玩家的操作,支持操作的撤销与重放。

7. 命令模式的扩展

7.1 宏命令(Macro Command)

命令模式的一个重要扩展是 宏命令(Macro Command)。宏命令是一种特殊的命令,它包含了多个命令对象,并通过一次执行操作,来顺序执行所有包含的命令。这在需要同时执行多个操作时非常有用。

class MacroCommand implements Command {private List<Command> commands = new ArrayList<>();public void addCommand(Command command) {commands.add(command);}@Overridepublic void execute() {for (Command command : commands) {command.execute();}}@Overridepublic void undo() {for (int i = commands.size() - 1; i >= 0; i--) {commands.get(i).undo();}}
}
7.2 队列请求(Queue Command)

命令模式可以与队列机制结合使用,将命令对象放入队列中进行异步处理,适用于任务调度系统。例如:银行的排队叫号系统。

8. 总结

命令模式是一种将请求封装为对象的行为型设计模式,它不仅解耦了请求发送者和接收者,还提供了更灵活的请求处理机制,支持撤销和恢复操作,并且易于扩展和维护。命令模式在实际应用中非常广泛,特别是在 GUI 事件处理、事务管理、任务调度等系统中,具有重要的应用价值。

通过合理使用命令模式,可以极大地提高系统的灵活性、可维护性和扩展性,是设计模式中非常有用的一种模式。

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

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

相关文章

零基础光伏人,数据计算轻松拿捏

在可再生能源领域&#xff0c;光伏产业以其清洁、可再生的特点日益受到全球关注。然而&#xff0c;对于初学者或“零基础光伏人”而言&#xff0c;光伏项目涉及的一系列数据计算和专业知识往往显得复杂而难以入手。幸运的是&#xff0c;随着技术的进步&#xff0c;一系列光伏计…

一文搞懂链表相关算法

目录 链表的逆序和截断 逆序 截断 查找链表的中间节点 力扣题 博主主页&#xff1a;东洛的克莱斯韦克-CSDN博客 链表的逆序和截断 逆序 推荐使用头插法逆序&#xff0c;首先要 new 一个虚拟头节点——newNode。如下图 链表的头节点为head&#xff0c;由cur指针指向head&a…

红外热成像技术开启光伏检测新视界

随着全球对可再生能源需求的不断增加&#xff0c;光伏发电系统的应用日益广泛。然而&#xff0c;光伏组件在长期运行中可能会出现各种故障&#xff0c;如热斑效应、隐裂、接线盒故障等&#xff0c;这些问题不仅影响光伏系统的发电效率&#xff0c;还可能引发安全隐患。 红外热成…

基于vue框架的的社区智慧养老系统1mo30(程序+源码+数据库+调试部署+开发环境)

系统程序文件列表 项目功能&#xff1a;老人,员工,老人档案,养生视频,社区医生,就医信息,在线咨询,咨询回复,菜品信息,点餐订单,服务预约,通知信息,服务评价,健康关爱,新闻公告,监控日志 开题报告内容 以下是一份基于Vue框架的社区智慧养老系统的开题报告&#xff0c;详细阐述…

龙蜥8.6 配置用户登录次数和锁定策略(已亲测)

操作系统&#xff1a;龙蜥8.6 x86_64 查看是否安装pam模块 rpm -qa | grep pam 查看可以使用的认证模块&#xff0c;因为有的系统是pam_tally2. cd /etc/pam.d ls 经过查看&#xff0c;该服务器是使用的pam_faillock 模块 打开/etc/pam.d/password-auth 的 PAM 配置文件…

【6.4】位运算-判断是否存在重复元素

一、题目 给定一个整数数组&#xff0c;判断 是否存在重复元素 。如果存在一值在数组中 出现至少两次 &#xff0c;函数返回 true 。如果数组中每个元素都不相同&#xff0c;则返回 false 。 示例 1: 输入: [ 1 , 2 , 3 , 1 ] 输出: true 示例 2: 输入: [ 1 , 2 , 3 , 4 ] 输出…

PCB打样下单流程

PCB打样下单流程 一、PCB打样在线下单流程1&#xff0e;平台登录2&#xff0e;PCB打样领券3&#xff0e;进入下单系统4&#xff0e;上传PCB文件5&#xff0e;PCB订单界面 PCB&#xff08;印刷电路板&#xff09;打样是验证设计、优化性能和推进项目进度的关键环节。随着互联网的…

Python爬虫知识体系-----正则表达式-----持续更新

数据科学、数据分析、人工智能必备知识汇总-----Python爬虫-----持续更新&#xff1a;https://blog.csdn.net/grd_java/article/details/140574349 文章目录 一、正则基础1. 为什么使用正则2. 正则与re模块简介 二、正则表达式1. 匹配单个字符与数字2. 限定符3. 定位符4. 选择匹…

yolo标签自动标注(使用python和yolo方法)

yolo代码自动标注 1.引言1.初阶“自动标注”&#xff0c;给每个图像都生成一个固定的标注文件&#xff0c;进而在labglimg中对矩形框进行微调&#xff0c;减少标注的工作量2.高阶自动标注&#xff0c;利用我们训练好的&#xff08;但是没有特别精准的&#xff09;yolo文件先对每…

在 WPF 中,如何使用命令来替代事件处理?

在 WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;命令是一种非常强大的替代传统事件处理的方法&#xff0c;特别适用于 MVVM&#xff08;Model-View-ViewModel&#xff09;架构。命令可以实现界面&#xff08;View&#xff09;和逻辑&#xff08;…

语音 AI 革命:未来,消费者更可能倾向于与 AI 沟通,而非人工客服

「未来&#xff0c;消费者更可能倾向于与 AI 沟通&#xff0c;而非人工客服&#xff0c;因为这将成为解决问题的最高效途径。」 这篇来自 Bessemer Venture Partners 的报告&#xff0c;是目前为止对语音 AI 在企业应用上最完整清晰的一次梳理。 核心要点&#xff1a; 尽管市…

过去几年电子学习的趋势

近年来&#xff0c;在技术和不断变化的学习者期望的推动下&#xff0c;电子学习已经发展成为一种适应性强、沉浸式和社会化的教育形式。个性化已成为最具影响力的趋势之一&#xff0c;Coursera和LinkedIn Learning等平台为个人量身定制内容。这些平台使用人工智能来建议课程、跟…

Java基础-Java多线程机制

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一、引言 二、多线程的基本概念 1. 线程与进程 2. 多线程与并发 3. 多线程的优势 三、Java多线程的实…

springboot 之 整合springdoc2.6 (swagger 3)

版本 springboot 3.3.5 jdk 17 springdoc 2.6.0 依赖pom <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.6.0</version> </dependency>注解对比…

Zabbix部署

1.集群规划 进程虚拟机节点1虚拟机节点2虚拟机节点3zabbix-agent√√√zabbix-server√PostgreSQL√zabbix-web√ 2.准备工作 默认在虚拟机节点2安装kafka、在虚拟机节点3安装redis 2.1关闭3台节点防火墙 sudo systemctl stop firewalld.service sudo systemctl disable fi…

如何优化锚文本来提升关键词排名?

锚文本在SEO中是个小细节&#xff0c;但作用可不小。它不仅能影响外链的质量&#xff0c;还直接影响你的目标关键词排名。你要知道&#xff0c;锚文本并不是随便加上就行&#xff0c;它得讲究技巧和策略。 锚文本的关键词选择一定要精准&#xff0c;且与页面内容高度相关。比如…

java项目-jenkins任务的创建和执行

参考内容: jenkins的安装部署以及全局配置 1.编译任务的general 2.源码管理 3.构建里编译打包然后copy复制jar包到运行服务器的路径 4.部署任务&#xff0c;执行部署脚本

怎么能够制作活码的二维码?在线生成活码的简单技巧

活码是现在很常用的一种二维码类型&#xff0c;可以用来展示日常生活中的视频、音频、图片、文件等多种类型的内容&#xff0c;有效提高内容分享的效率&#xff0c;可以让更多人同时扫码获取内容。使用二维码来展示内容&#xff0c;用户也不需要下载或者保存内容&#xff0c;扫…

谷歌SEO为什么是一场持久战?

很多人在刚开始做SEO时&#xff0c;都会满怀期待&#xff0c;希望能在短时间内看到显著的效果。但很快&#xff0c;他们就会发现&#xff0c;这是一场需要耐心的持久战。谷歌的算法非常复杂&#xff0c;每天都在调整优化&#xff0c;你今天做的改动&#xff0c;可能要几个月后才…

6TS Series TVS 的 解析

6TS Series 600W Transient Voltage Suppresso指的是一系列高性能的瞬态电压抑制二极管&#xff08;Transient Voltage Suppressor&#xff0c;TVS&#xff09;&#xff0c;这些二极管由时源芯微科技&#xff08;TimeSource&#xff09;设计用于保护敏感的电子设备免受雷击、电…