技术成神之路:设计模式(二十二)命令模式

devtools/2024/10/27 20:56:09/

在这里插入图片描述
相关文章:技术成神之路:二十三种设计模式(导航页)

介绍

命令模式(Command Pattern)是一种行为设计模式,允许将请求(命令)封装为对象,从而使您可以使用不同的请求、队列或记录请求日志,以及支持可撤销操作。

1. 定义


命令模式将一个请求封装为一个对象,从而能够参数化其他对象以便于请求的发起、排队或日志记录。

2. 主要作用


  • 将请求调用者与请求接收者解耦。
  • 支持请求的排队和日志记录。
  • 支持可撤销操作。

3.解决的问题


命令模式主要解决的是请求的发送者和接收者之间的紧耦合。通过将请求封装为对象,命令模式能够灵活地设计和扩展请求的处理。

4.模式原理


包含角色:

  1. 命令接口(Command): 定义执行命令的接口。
  2. 具体命令类(ConcreteCommand): 实现命令接口,定义与接收者之间的绑定。
  3. 接收者(Receiver): 知道如何执行与某个请求相关的操作。
  4. 调用者(Invoker): 持有命令对象并在需要时调用它。

UML类图:
在这里插入图片描述
示例代码:
通过Command接口和具体命令类实现了对请求的封装,RemoteControl类可以通过调用不同的命令来触发不同的行为。

// 命令接口
interface Command {void execute();void undo();
}// 命令接收者
class Light {public void on() {System.out.println("Light is ON");}public void off() {System.out.println("Light is OFF");}
}// 具体命令类
class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}@Overridepublic void undo() {light.off();}
}class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}@Overridepublic void undo() {light.on();}
}// 命令调用者
class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}public void pressUndo() {command.undo();}
}

调用

public class CommandPatternDemo {public static void main(String[] args) {Light light = new Light();Command lightOn = new LightOnCommand(light);Command lightOff = new LightOffCommand(light);RemoteControl remote = new RemoteControl();remote.setCommand(lightOn);remote.pressButton();remote.pressUndo();remote.setCommand(lightOff);remote.pressButton();remote.pressUndo();}
}

打印输出

Light is ON
Light is OFF
Light is OFF
Light is ON

命令模式可能理解起来稍微麻烦一些,毕竟角色比较多,将示例代码和上面UML类图结合起来看,会更容易理解。

看到这个模式,让我想起了之前做过的一个项目,需要上位机和下位机或蓝牙模块不停的进行通信,接收和发送实时数据,指令要根据具体协议进行传输,都是字节数组,指令是按帧进行传输的,一条指令本身包括长度,校验和,头字节,尾字节等关键信息,附加的信息还有发送间隔,指令类型如485 或 232等,为了统一管理这些指令,就统一提取了命令接口

为了防止指令发送顺序,使用到了队列,不停地喂数据,发送线程不停地取数据,这里的数据就是一个一个的具体命令对象,将命令取出来后,根据其内部信息,再判断是向下位机发送还是蓝牙模块发送,突然发现命令模式好像专门因这个场景而诞生的,哈哈哈。

多说两句,管理和发送不同协议的指令还不算太难,难的是通过一个数据接收类,统一接收并区别不同的指令,然后在不同的地方处理才是最难的,少则有两个不同协议,多则三个或以上,它们发过来都是一段字节数据,有可能是完整的指令,有可能只是一段指令,你不知道它是哪个协议的,只能将数据放到一个很大的字节数组中,供后续拼接,然后再不停的校验,而且要做到毫秒级提取,慢一点存放字节容器就会爆满,每种协议都有自己单独的校验方式,奇校验、偶校验、累加和,异或… 光是听到都头大,最后将领导写的初版代码,优化、验证、重写了无数遍,才完全理解,最后将领导的代码删了,使用了我的版本(可以平替,支持更多校验方式,更容易理解的代码),哈哈哈哈,一个能吹nb的功能。

说的有点多了,但那段回忆,一下就上来了,不吐不快。

5.优缺点


优点:

  • 降低了系统的耦合度。
  • 增强了系统的灵活性和可扩展性。
  • 可以很方便地添加新的命令。

缺点:

  • 需要创建许多类,增加了系统的复杂性。
  • 如果命令过多,可能会导致系统的可维护性降低。

6.应用场景


  • 界面菜单系统。
  • 实现Undo/Redo功能。
  • 请求需要排队的场景。

7.总结


命令模式通过将请求封装为对象,提供了灵活的请求处理方式。它有助于实现请求的解耦、可撤销操作和请求日志。尽管它增加了类的数量,但在需要复杂请求处理的系统中,它的优势是显而易见的。


http://www.ppmy.cn/devtools/129260.html

相关文章

写一个 qq自动回话的程序

这是一个简单的 QQ 自动回话的 Python 程序示例: import random# 定义问题和回答的字典 qa_dict {"你好": ["你好!", "嗨!", "你好啊!"],"你今年多大了": ["我是一个程…

Spring Boot论坛网站:微服务架构的实践

摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了论坛网站的开发全过程。通过分析论坛网站管理的不足,创建了一个计算机管理论坛网站的方案。文章介绍了论坛网站的系统分析部分,包括可行性…

人工智能:塑造未来生活与工作的力量

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《热点时事》 期待您的关注 引言 随着人工智能技术的不断发展,我们已经看到了它在各行业带来的巨大变革。 在医疗行业中…

linux上部署多个python环境并在jupyterlab搭建各自的虚拟环境virtualenv

linux上部署多个python环境并在jupyterlab搭建各自的虚拟环境virtualenv 一,Linux部署多个python环境 到官网https://www.python.org下载python指定 连接Linux服务器,进入到指定目录下 cd /usr/local/python因为该服务器上会搭建较多版本的python&…

git pull过程中出现there is no tracking information for the current branch

在本地开发的过程中git pull 拉取代码时出现There is no tracking information for the current branch 这个时候证明的是本地代码分支没有远程的跟踪信息也就是说与远程的分支建立联系,所以导致拉取代码无法成功 其实可视化窗口已经给了解决方案 git branch --se…

require和import的区别

require 和 import 是 JavaScript 中用于模块加载的两种不同语法,它们在使用方式、执行时机和兼容性方面有一些重要的区别。此外,懒加载是一种优化技术,可以提高应用的性能。 require 与 import 的区别 1. 语法 require: 语法:c…

基于opencv答题卡识别判卷

项目源码获取方式见文章末尾! 回复暗号:13,免费获取600多个深度学习项目资料,快来加入社群一起学习吧。 **《------往期经典推荐------》**项目名称 1.【基于DDPG算法的股票量化交易】 2.【卫星图像道路检测DeepLabV3Plus模型】 3…

黑马javaWeb笔记重点备份12:yml格式配置文件

yml配置文件 介绍 在springboot项目当中是支持多种配置方式的,除了支持properties配置文件以外,还支持另外一种类型的配置文件,就是我们接下来要讲解的yml格式的配置文件。 application.properties server.port8080 server.address127.0.0.…