03-JAVA设计模式-命令模式

ops/2024/10/25 16:26:02/

命令模式

什么是命令模式

命令模式(Command Pattern)是一种行为设计模式,它将请求封装为对象,从而使你可用不同的请求把客户端与请求的处理者解耦,也称动作模式或事物模式。

命令模式中,命令对象封装了接收者对象的动作,调用者通过调用命令对象来执行该动作,而无需知道具体的接收者对象是谁。

命令模式的主要角色包括:

  • 命令接口(Command): 声明一个执行操作的接口。
  • 具体命令(ConcreteCommand): 实现命令接口,将接收者对象绑定于一个动作,调用接收者对象的相应操作,以实现execute()方法。
  • 请求者(Invoker): 要求命令执行一个请求。
  • 接收者(Receiver): 知道如何执行与请求相关联的操作的类。
  • 客户端(Client): 创建一个具体命令对象,并设置其接收者。

优点:

  • 解耦请求者和接收者:命令模式中,请求者不直接与接收者交互,而是通过命令对象进行中介,这彻底消除了请求者与接收者之间的耦合。这种解耦使得请求者和接收者可以独立变化,提高了系统的灵活性和可维护性。
  • 支持撤销和重做: 由于命令对象封装了操作,因此可以很容易地实现对请求的撤销和重做功能。这对于需要支持用户撤销操作或实现事务回滚的系统来说非常有用。
  • 可记录日志和监控: 命令对象可以被保存到持久化的媒介中,用于记录操作日志或进行监控。这对于审计、追踪和调试等操作非常有帮助。
  • 易于扩展和组合: 新的命令可以很容易地添加到系统中,而不影响现有的代码。此外,命令对象还可以组合起来形成更复杂的操作序列。

缺点:

  • 可能导致过多的具体命令类: 对于每个请求接收者的调用操作,都需要设计一个具体命令类。在某些系统中,如果请求接收者的操作种类繁多,那么可能会导致系统中存在大量的具体命令类,这会增加系统的复杂性。
  • 可能增加系统开销: 由于每个请求都需要通过命令对象进行中介,因此相对于直接调用接收者对象的方法,命令模式可能会增加一些额外的系统开销。

常见运用场景包括:

  • GUI设计中的按钮点击事件: 在图形用户界面设计中,按钮的点击事件可以通过命令模式进行处理。每个按钮的点击事件可以关联一个命令对象,当按钮被点击时,执行相应的命令。
  • 撤销/重做操作: 在需要支持撤销和重做功能的系统中,命令模式可以很好地实现这一需求。通过保存每次操作的命令对象,可以在需要时执行撤销或重做操作。
  • 事务处理: 在需要确保一系列操作要么全部成功要么全部失败(即原子性)的系统中,可以使用命令模式来封装这些操作,并在一个命令对象中执行它们。如果某个操作失败,可以回滚整个命令对象,确保数据的一致性。
  • 日志记录: 对于那些需要记录用户操作日志的系统,命令模式可以将每个操作封装为一个命令对象,并将其保存到日志中,以便后续查看和分析。

案例

通过命令模式实现电灯的开/关

UML

在这里插入图片描述

实现步骤:

  • 创建命令的具体执行者Light,定义电灯的具体执行开关的方法
  • 创建命令接口,定义执行的抽象方法
  • 创建具体命令接口的实现,通过持有具体执行的引用,执行指定命令
  • 创建请求者,用于发出指令,处理请求指令

实现代码

Light.java

java">// 命令的接收者
public class Light {public void on() {System.out.println("Light is on");}public void off() {System.out.println("Light is off");}
}

Command.java

java">// 命令接口
public interface Command {// 执行动作void execute();
}

LightOnCommand.java

java">// 命令接口的具体实现
public class LightOnCommand implements Command{// 持有命令接受者的引用private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}
}

LightOffCommand.java

java">// 命令接口的具体实现
public class LightOffCommand implements Command{// 持有命令接受者的引用private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}
}

SimpleRemoteControl.java

java">// 请求者:持有命令接口的实现,用于处理命令请求
public class SimpleRemoteControl {// 持有命令接口的实现private Command command;public void setCommand(Command command) {this.command = command;}// 执行动作public void excute(){command.execute();}
}

执行结果:
在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git


http://www.ppmy.cn/ops/8349.html

相关文章

JS stacktrace 堆内存耗尽

javascript 堆内存耗尽 问题 是 npm run dev 的时候 报错 如下 <--- JS stacktrace --->FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory在大多数情况下&#xff0c;默认情况下 Node.js 的堆内存…

基于SSM+Jsp+Mysql的文物管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

2024.4.19作业

1.总结二进制信号量和计数型信号量的区别&#xff0c;以及他们的使用场景。 二进制信号量只有0和1两个状态&#xff0c;如果信号被一个线程接收&#xff0c;那别的线程就无法接收此信号 计数型信号可以累计&#xff0c;可以被多个线程接收 2.使用计数型信号量完成生产者和消费…

千锤百炼之算法Scanner和System.out引起超时解决办法

题外话 觉得这个内容还是很关键的,过来写一下吧 本次内容有点抽象大家试着听一下 正题 做过算法题的人都知道,无论是在力扣还是牛客或者别的网站刷题,很多情况下都会遇到输入输出的情况,当我们用Scanner和System.out.print()就有可能产生超时问题 如下图 接下来会有一段代…

vue-router学习2:路由导航方式

声明式导航 声明式导航方式在Vue Router中主要通过<router-link>组件来实现&#xff0c;它允许你直接在模板中创建导航链接&#xff0c;而无需编写额外的JavaScript代码。以下是一些常见的声明式导航方式及其示 1. 基本的导航链接 使用<router-link>组件&#x…

【Spring】Spring MVC入门

Spring MVC入门 一、什么是Spring Web MVC&#xff1f; 1.1 MVC定义 MVC是Model View Controller的缩写&#xff0c;是一种软件架构的设计模式&#xff0c;将软件系统分为模型、视图、控制器三个部分。 示意图如下: 可以看到&#xff0c;Controller作为一个“粘合剂”处于M…

政安晨:【深度学习神经网络基础】(八)—— 神经网络评估回归与模拟退火训练

目录 简述 评估回归 模拟退火训练 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 简述 深度学习神经网…

纽扣电池卖家注意!美国纽扣电池UL4200A标准更新

2023年9月21日&#xff0c;美国消费品安全委员会CPSC(Consumer Product Safety Commission) 决定采用UL 4200A-2023&#xff08;包含纽扣电池或硬币电池的产品安全标准&#xff09;作为包含纽扣电池或硬币电池的消费品的强制性消费品安全规则&#xff0c;相关要求同时被编入到1…