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

在这里插入图片描述

介绍

命令模式(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.rhkb.cn/news/455147.html

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

相关文章

S32DS for ARM GPIO实践

S32DS操作: 一、新建项目 打开S32DS,FIle–>NEW–> S32DS Application Project选择对应芯片,写入项目名然后下一步 选择对应的SDK,Debugger选带有PE字眼的,点击完成 配置GPIO,双击Components界面下的…

【MySQL】详解MySQL数据类型

一、数据类型 各类型的数值范围: 在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。 可以通过UNSIGNED来说明某个字段是无符号的。对于int类型可能存放不下的数据,尽量不使用unsigned,unsigned int 同样可…

pytorch dataloader学习

import torch from torch.utils.data import Dataset, DataLoader import numpy as np torch.manual_seed(1) # 自定义数据集 class CustomDataset(Dataset):def __init__(self):# 创建一些示例数据(100个样本,每个样本包含10个特征)self.dat…

推荐一个开源非线性视频编辑器:Kdenlive

Kdenlive是一个开源的视频编辑软件,项目始于约2003年。它基于Qt和KDE框架库构建,大部分视频处理由MLT框架完成,同时依赖其他开源项目如FFmpeg、frei0r、movit、ladspa、sox等。 软件特点: - 多轨视频编辑:支持多个音频…

MongoDB Shell 基本命令(三)生成学生脚本信息和简单查询

一、生成学生信息脚本 利用该脚本可以生成任意个学生信息,包括学号、姓名、班级、年级、专业、课程名称、课程成绩等信息,此处生成2万名学生,学生所有信息都是给定范围后随机生成。 生成学生信息后,再来对学生信息进行简单查询。…

论文阅读:Guided Linear Upsampling

今天介绍一篇有趣的文章,Guided Linear Upsampling,基于引导的线性上采样,这是发表在 ACM transaction on Graphic 的一篇工作。 Abstract 引导上采样是加速高分辨率图像处理的一种有效方法。在本文中,文章作者提出了一种简单而…

【2024】【字节青训营】:字节青训营入营测试题——Java版本(已提交通过)

目录 简单题目 计算x到y的最小步数 环状 DNA 序列的最小表示法 Base32 解码和编码 打点计时器 兔群繁殖之谜 完美整数 找出整数数组中占比超过 一半 的数 找出最长的神奇数列 找单独的数 字符串最短循环字串 二进制反码转换问题 中等题目 简单四则运算 数字翻译…

【图解版】力扣第146题:LRU缓存

力扣第146题:LRU缓存 一、LRU算法1. 基本概念2. LRU 和 LFU 的区别:3. 为什么 LRU 不需要记录使用频率? 二、Golang代码实现三、代码图解1. LRUCache、DLinkedNode两个结构体2. 初始化结构体对象3. addToHead函数4. removeNode函数5. moveToH…

rust grpc demo

文章目录 1. 创建项目2. 配置proto2.1 配置Cargo.toml, 内容如下:2.2 创建文件proto/hello.proto, 内容如下:2.3 添加build.rs文件, 内容如下:2.4 项目结构如下:2.5 编译proto文件 3.0 处理服务3.1 项目引入3.2 添加sr…

多模态大语言模型(MLLM)-Deepseek Janus

论文链接:https://arxiv.org/abs/2410.13848 代码链接:https://github.com/deepseek-ai/Janus 本次解读Janus: Decoupling Visual Encoding for Unified Multimodal Understanding and Generation 前言 Deepseek出品,必属精品。 创新点 传…

docker容器无法连接宿主机mysql排查

1、docker无法访问宿主机 在docker容器内,需要访问当前docker容器的网关,例如172.xx.0.1,即可访问宿主机,因此需要保证docker的网络配置正确 查看当前docker容器的网关: docker inspect 你的容器名或者容器id 显示…

【纯前端excel导出】vue2纯前端导出excel,使用xlsx插件,修改样式、合并单元格

官网: 1、xlsx-js-style xlsx-js-style | xlsx-js-style homepage 2、xlsx SheetJS 中文网 一、使用第三方插件 1、安装 npm install xlsx-js-style 2、引入 import xlsx from xlsx-js-style xlsx插件是基础的导出,不可以修改样式,直接xlsx-s…

文通车牌识别相机在工地称重应用中的卓越表现

在现代工地管理中,高效、准确的称重系统是确保工程顺利进行的关键之一。而文通车牌识别相机的出现,为工地称重应用带来了全新的解决方案。 一、工地称重面临的挑战 传统的工地称重方式往往存在着一些问题。人工记录车牌和重量信息容易出现错误&#xff0…

python-----函数详解(一)

一、概念及作用: 概念:由若干条语句组成语句块,其中包括函数名称、参数列表,它是组织代码的最小单元,完成一定的功能 作用:把一个代码封装成一个函数,一般按功能组织一段代码 目的就是为了重…

基于单片机的智能小区门禁系统设计(论文+源码)

1总体架构 智能小区门禁系统以STM32单片机和WiFi技术为核心,STM32单片机作为主控单元,通过WiFi模块实现与手机APP的连接,构建整个门禁系统。系统硬件包括RFID模块、指纹识别模块、显示屏、按键以及继电器。通过RFID绑定IC卡、APP面部识别、指…

百度搜索推广和信息流推广的区别,分别适用于什么场景!

信息流推广和搜索广告,不仅仅是百度,是很多平台的两个核心推广方式。 1、搜索广告: 就是基于用户的搜索习惯,更多是用户有疑问、还有用户当下就要做出行动的广告。 比如上门服务、线上咨询服务、招商加盟、了解产品各种型号和信…

STM32G4系列MCU的低功耗模式介绍

目录 概述 1 认识低功耗模式 1.1 低功耗模式的应用 1.2 低功耗模式介绍 2 低功耗模式的状态关系 2.1 低功耗模式可能的转换状态图 2.2 低功耗模式总结 3 运行模式 3.1 减慢系统时钟 3.2 外围时钟门控 3.3 低功耗运行模式(LP运行) 概述 本文主…

react 基础学习笔记

1.react 语法 ①数据渲染 函数组件将HTML结构直接写在函数的返回值中 JSX只能有一个根元素 JSX插值写法 插值可以使用的位置 1.标签内容; 2.标签属性 JSX 条件渲染:三目运算符; JSX根据数据进行列表渲染:map()方法&#x…

QT 机器视觉 1.相机类型

本专栏从实际需求场景出发详细还原、分别介绍大型工业化场景、专业实验室场景、自动化生产线场景、各种视觉检测物体场景介绍本专栏应用场景 更适合涉及到视觉相关工作者、包括但不限于一线操作人员、现场实施人员、项目相关维护人员,希望了解2D、3D相机视觉相关操作…

微服务与多租户详解:架构设计与实现

引言 在现代软件开发领域,微服务架构和多租户架构是两个重要的概念。微服务架构通过将应用程序拆分为多个独立的服务,提升了系统的灵活性和可维护性。而多租户架构则通过共享资源来服务多个客户,提高了资源利用率和系统的经济性。 一、微服务…