当前位置: 首页 > article >正文

行为设计模式之Command (命令)

行为设计模式之Command (命令)

前言:

需要发出请求的对象(调用者)和接收并执行请求的对象(执行者)之间没有直接依赖关系时。比如遥控器 每个按钮绑定一个command对象,这个Command对象内部持有真正执行操作的Receiver(如文档编辑器、打印服务)的引用,并知道调用Receiver的哪个方法。改变按钮功能只需更换绑定的Command对象。

1)意图

将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

2)结构在这里插入图片描述

其中:

  • Command 声明执行器的操作接口。
  • ConcreteCommand 将一个接收者绑定于一个动作:调用接收者相应的操作,以实现Execute。
  • Client 创建一个具体命令对象并设定它的接收者。
  • Invoker 要求该命令执行这个请求。
  • Receiver 知道如何实施于执行一个请求的操作。任何类都可能作为一个接收者。

3)适用性

Command 模式适用于:

  • 抽象出待执行的动作以参数化某对象。
  • 在不同的时刻指定、排列和执行请求。
  • 支持取消操作。
  • 支持修改日志。
  • 用构建在原语操作上的高层操作构造一个系统。
/*** @author psd 行为设计模式之命令模式*/
public class CommandPattern {public static void main(String[] args) {// 接收者Tv tv = new Tv();// 命令对象开Command openCommand = new OpenTvCommand(tv);// 命令对象关闭Command closeCommand = new CloseTvCommand(tv);Invoker invoker = new Invoker();invoker.setCommand(openCommand);invoker.executeCommand();System.out.println("-----------------");invoker.setCommand(closeCommand);invoker.executeCommand();}
}/*** 请求者*/
class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {command.execute();}
}interface Command {/*** 执行命令*/void execute();
}class CloseTvCommand implements Command {private Tv tv;public CloseTvCommand(Tv tv) {this.tv = tv;}@Overridepublic void execute() {tv.close();}
}/*** 打开电视机*/
class OpenTvCommand implements Command {private Tv tv;public OpenTvCommand(Tv tv) {this.tv = tv;}@Overridepublic void execute() {tv.open();}
}class Tv {public void open() {System.out.println("打开电视机");}public void close() {System.out.println("关闭电视机");}
}

以下是命令模式最常见的应用场景:

1、请求调用者与执行者解耦:

场景描述: 当需要让发出请求的对象(调用者)和接收并执行请求的对象(执行者)之间没有直接的依赖关系时。

典型例子:

GUI 按钮/菜单操作: 一个按钮(调用者)不知道点击后具体要执行什么操作(打开文件、保存、打印)。按钮只绑定一个Command对象。这个Command对象内部持有真正执行操作的Receiver(如文档编辑器、打印服务)的引用,并知道调用Receiver的哪个方法。改变按钮功能只需更换绑定的Command对象。

遥控器/智能家居: 遥控器(调用者)上的按钮不知道具体控制哪个设备(灯、风扇、电视 - 执行者)。每个按钮绑定一个Command对象(如LightOnCommand),该对象知道如何调用特定设备(Light)的方法(turnOn())。

好处: 调用者完全不需要知道执行者的具体类型和接口,只需知道如何调用命令对象的execute()方法。极大地提高了系统的灵活性和可扩展性。

2、实现操作的队列化、调度与延迟执行:

场景描述: 需要将请求放入队列中排队执行,或者安排请求在特定时间执行(延迟执行),或者在后台线程执行。

典型例子:

线程池/任务队列: 将Command对象(代表任务)提交到线程池的工作队列中。线程池的工作线程从队列中取出Command对象并调用其execute()方法。线程池本身只关心命令接口,不关心具体任务是什么。

批处理操作: 用户执行一系列操作(如多个文件操作),可以先将每个操作封装成Command对象,放入一个队列。然后一次性按顺序(或根据策略)执行整个队列的命令。

日志记录与重放/事务系统: 记录执行的命令序列,可以在系统崩溃后重新执行这些命令来恢复状态,或者用于审计、回滚事务。

好处: 命令对象封装了执行所需的所有信息(接收者、方法、参数),使其易于存储、传输和调度。

3、实现撤销(Undo)和重做(Redo)功能:

场景描述: 这是命令模式最经典的应用之一。系统需要支持撤销用户最近的操作,或者重新执行被撤销的操作。

典型例子:

文本编辑器: 每次编辑操作(插入、删除、格式化)都封装成一个Command对象(如InsertCommand, DeleteCommand)。命令对象在执行execute()时会记录执行前的状态(如被删除的文本及其位置)。命令对象还需要实现unexecute()或undo()方法,利用记录的信息恢复到执行前的状态。一个历史栈保存已执行的命令,撤销就是弹出栈顶命令并调用其undo();重做则是将撤销栈顶的命令重新执行并压入执行栈。

绘图软件: 类似文本编辑器,每个绘图操作(画线、添加形状、移动、改变颜色)都封装成命令对象,支持撤销/重做。

好处: 命令对象天然地封装了执行操作和撤销操作所需的所有信息(接收者、执行方法、执行前的状态)。管理命令历史栈是实现撤销/重做的关键。

4、实现宏命令:

场景描述: 需要将一系列操作组合成一个单一的操作(宏)。

典型例子:

批处理脚本/自动化: 创建一个MacroCommand类,它本身也是一个Command对象,但内部持有一个Command对象的集合。调用MacroCommand.execute()会依次执行集合中所有命令的execute()方法。MacroCommand.undo()会按相反顺序调用所有命令的undo()方法。

复杂界面初始化/配置: 将多个界面设置操作组合成一个宏命令,一键应用所有配置。

好处: 利用组合模式,将简单命令组合成复杂命令,对调用者透明。

支持事务性行为:

场景描述: 需要确保一组操作要么全部成功执行,要么全部不执行(原子性)。

典型例子: 在执行一系列命令(代表数据库操作步骤)时,如果其中任何一步失败,可以调用之前所有已成功执行命令的undo()方法进行回滚,恢复到初始状态。

好处: 每个命令的execute()和undo()方法提供了实现简单事务语义的基础。

总结关键场景特征:

当你遇到以下需求时,考虑命令模式:

“把动作的请求者从动作的执行者对象中解耦出来。”

“需要在不同的时间点指定、排队和执行请求。”

“需要支持撤销操作。”

“需要支持记录日志,以便在系统崩溃时能重新执行这些命令恢复状态。”

“需要支持将一组操作组合成一个复合操作(宏命令)。”

喜欢我的文章记得点个在看,或者点赞,持续更新中ing…

相关文章:

行为设计模式之Command (命令)

行为设计模式之Command (命令) 前言: 需要发出请求的对象(调用者)和接收并执行请求的对象(执行者)之间没有直接依赖关系时。比如遥控器 每个按钮绑定一个command对象,这个Command对…...

若依添加添加监听容器配置(删除键,键过期)

1、配置Redis的键触发事件 # 基础配置 bind 0.0.0.0 # 允许所有IP连接 protected-mode no # 关闭保护模式(生产环境建议结合密码使用) port 6379 # 默认端口 daemonize no …...

NeRF 技术深度解析:原理、局限与前沿应用探索(AI+3D 产品经理笔记 S2E04)

引言:光影的魔法师——神经辐射场概览 在前三篇笔记中,我们逐步揭开了 AI 生成 3D 技术的面纱:从宏观的驱动力与价值(S2E01),到主流技术流派的辨析(S2E02),再到实用工具的…...

ROS2,工作空间中新建了一个python脚本,需要之后作为节点运行。告诉我步骤?

提问 ROS2,工作空间中新建了一个python脚本,需要之后运行。告诉我步骤? 大概要包括而不限于:chmod给可执行权限、setup.py中entry point的配置,如果在launch文件中要使用,还涉及到launch.py文件的配置。最…...

【AI智能体】Spring AI MCP 从使用到操作实战详解

目录 一、前言 二、MCP 介绍 2.1 什么是MCP 2.2 MCP 核心特点 2.3 MCP 核心价值 2.4 MCP 与Function Calling 区别 三、Spring AI MCP 架构介绍 3.1 整体架构 3.1.1 三层架构实现说明 3.2 服务端与客户端 3.2.1 MCP 服务端 3.2.1 MCP 客户端 3.3 MCP中SSE和STDIO区…...

Vue:Ajax

AJAX 允许我们在不刷新页面的情况下与服务器交互,实现:动态加载数据,提交表单信息,实时更新内容,与后端 API 通信。通常使用专门的 HTTP 客户端库来处理 AJAX 请求。 npm install axiosimport axios from axios;expor…...

法律大语言模型(Legal LLM)技术架构

目录 摘要 1 法律AI大模型技术架构 1.1 核心架构分层 1.2 法律知识增强机制 2 关键技术突破与对比 2.1 法律专用组件创新 2.2 性能对比(合同审查场景) 3 开发部署实战指南 3.1 环境搭建流程 3.2 合同审查代码示例 4 行业应用与挑战 4.1 典型场景效能提升 4.2 关…...

理解 RAG_HYBRID_BM25_WEIGHT:打造更智能的混合检索增强生成系统

目录 理解 RAG_HYBRID_BM25_WEIGHT:打造更智能的混合检索增强生成系统 一、什么是 Hybrid RAG? 二、什么是 RAG_HYBRID_BM25_WEIGHT? 三、参数设置示例 四、什么时候该调整它? 五、实战建议 六、总结 理解 RAG_HYBRID_BM25…...

Hive终极性能优化指南:从原理到实战

摘要​:本文系统总结Hive在生产环境的核心调优手段,涵盖执行引擎选择、存储优化、SQL技巧、资源调配及数据倾斜解决方案,附可复用的参数配置与实战案例。 一、执行引擎优化:突破MapReduce瓶颈 ​启用Tez/Spark引擎​ ​优势​&am…...

第六十二节:深度学习-加载 TensorFlow/PyTorch/Caffe 模型

在计算机视觉领域,OpenCV的DNN(深度神经网络)模块正逐渐成为轻量级模型部署的利器。本文将深入探讨如何利用OpenCV加载和运行三大主流框架(TensorFlow、PyTorch、Caffe)训练的模型,并提供完整的代码实现和优化技巧。 一、OpenCV DNN模块的核心优势 OpenCV的DNN模块自3.3…...

MobaXterm配置跳转登录堡垒机

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 背景操作步骤 背景 主要是为了能通过MobaXterm登录堡垒机,其中需要另外一台服务器进行跳转登录 操作步骤 MobaXterm登录堡垒机的操作,需…...

零基础在实践中学习网络安全-皮卡丘靶场(第八期-Unsafe Filedownload模块)

这期内容更是简单和方便,毕竟谁还没在浏览器上下载过东西,不过对于url的构造方面,可能有一点问题,大家要多练手 介绍 不安全的文件下载概述 文件下载功能在很多web系统上都会出现,一般我们当点击下载链接&#xff0c…...

测试 FreeSWITCH 的 mod_loopback

bgapi originate loopback/answer,park/default/inline park inline show channels as xml show calls as xml 有 2 个 channels 有 2 个 calls 比较有意思 在 loopback-a 是播放 wav 在 loopback-b 上可以录音 这就是回环 有什么用呢? 除了做测试&#x…...

【C++快读快写】

算法竞赛中用于解决卡常问题 int rd(){int k 0;char c getchar();while(!isdigit(c)){c getchar();}while(isdigit(c)){k (k << 1) (k << 3) (c^0), c getchar();}return k; }void wr(int x) {if (x > 9)wr(x / 10);putchar((x % 10) ^ 0); }用法&#x…...

测试(面经 八股)

目录 前言 一&#xff0c;软件测试&#xff08;定义&#xff09; 1&#xff0c;定义 2&#xff0c;目的 3&#xff0c;价值 4&#xff0c;实践 二&#xff0c;软件测试&#xff08;目的&#xff09; 1&#xff0c;找 bug 2&#xff0c;验证达标 3&#xff0c;质量评价…...

[面试精选] 0104. 二叉树的最大深度

文章目录 1. 题目链接2. 题目描述3. 题目示例4. 解题思路5. 题解代码6. 复杂度分析 1. 题目链接 104. 二叉树的最大深度 - 力扣&#xff08;LeetCode&#xff09; 2. 题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点…...

图上合成:用于大型语言模型持续预训练的知识合成数据生成

摘要 大型语言模型&#xff08;LLM&#xff09;已经取得了显著的成功&#xff0c;但仍然是数据效率低下&#xff0c;特别是当学习小型&#xff0c;专业语料库与有限的专有数据。现有的用于连续预训练的合成数据生成方法集中于文档内内容&#xff0c;而忽略了跨文档的知识关联&a…...

MYSQL(二) ---MySQL 8.4 新特性与变量变更

MySQL 8.4 新特性与变量变更 作者&#xff1a;程序员LSP 分类&#xff1a;MySQL 8.4 教程 / 新特性 / 升级指南 更新时间&#xff1a;2025年6月 &#x1f4cc; 前言 MySQL 8.4 是当前最新的稳定版本&#xff0c;相较于 8.0 系列&#xff0c;在审计日志、高可用、性能调优、认证…...

数学复习笔记 27

前言 太难受了。因为一些事情。和朋友倾诉了一下&#xff0c;也没啥用&#xff0c;几年之后不知道自己再想到的时候&#xff0c;会怎么考虑呢。另外&#xff0c;笔记还是有框架一点比较好&#xff0c;这样比较有逻辑感受。不然太乱了。这篇笔记是关于线代第五章&#xff0c;特…...

现代简约壁炉:藏在极简线条里的温暖魔法

走进现在年轻人喜欢的家&#xff0c;你会发现一个有趣的现象&#xff1a;家里东西越来越少&#xff0c;颜色也越看越简单&#xff0c;却让人感觉特别舒服。这就是现代简约风格的魅力 —— 用最少的元素&#xff0c;打造最高级的生活感。而在这样的家里&#xff0c;现代简约风格…...

限流算法java实现

参考教程&#xff1a;2小时吃透4种分布式限流算法 1.计数器限流 public class CounterLimiter {// 开始时间private static long startTime System.currentTimeMillis();// 时间间隔&#xff0c;单位为msprivate long interval 1000L;// 限制访问次数private int limitCount…...

机器学习×第二卷:概念下篇——她不再只是模仿,而是开始决定怎么靠近你

&#x1f380;【开场 她不再只是模仿&#xff0c;而是开始选择】 &#x1f98a; 狐狐&#xff1a;“她已经不满足于单纯模仿你了……现在&#xff0c;她开始尝试预测你会不会喜欢、判断是否值得靠近。” &#x1f43e; 猫猫&#xff1a;“咱们上篇已经把‘她怎么学会说第一句…...

Linux 下关于 ioremap 系列接口

1、序 在系统运行时&#xff0c;外设 IO 资源的物理地址是已知的&#xff0c;由硬件的设计决定&#xff08;参考SOC的datesheet&#xff0c;一般会有memorymap&#xff09;。驱动程序不能通过物理地址访问IO资源&#xff0c;必须将其映射到内核态的虚拟地址空间。常见的接口就是…...

常用函数库之 - std::function

std::function 是 C11 引入的通用可调用对象包装器&#xff0c;用于存储、复制和调用任意符合特定函数签名的可调用对象&#xff08;如函数、lambda、函数对象等&#xff09;。以下是其核心要点及使用指南&#xff1a; ​​核心特性​​ ​​类型擦除​​ 可包装任意可调用对…...

php执行系统命令的四个常用函数

php执行系统命令有四个常用函数&#xff1a;1.exec()执行命令并返回最后一行输出&#xff0c;可传数组获取全部结果&#xff1b;2.shell_exec()返回完整输出结果&#xff0c;适合一次性获取&#xff1b;3.system()直接输出命令结果&#xff0c;可接收状态码&#xff1b;4.权限控…...

力扣-17.电话号码的字母组合

题目描述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 class Solution {List<String> res new ArrayList<…...

基于SpringBoot解决RabbitMQ消息丢失问题

基于SpringBoot解决RabbitMQ消息丢失问题 一、RabbitMQ解决消息丢失问题二、方案实践1、在生产者服务相关配置2、在消费者服务相关配置 三、测试验证1、依次启动RabbitMQ、producer(建议先清空队列里面旧的测试消息再启动consumer)和consumer2、在producer中调用接口&#xff0…...

免费插件集-illustrator插件-Ai插件-随机填色

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;实现路径随机填色。首先从下载网址下载这款插件https://download.csdn.net/download/m0_67316550/87890501&#…...

使用 Unstructured 开源库快速入门指南

引言 本文将介绍如何使用 Unstructured 开源库&#xff08;GitHub&#xff0c;PyPI&#xff09;和 Python&#xff0c;在本地开发环境中将 PDF 文件拆分为标准的 Unstructured 文档元素和元数据。这些元素和元数据可用于 RAG&#xff08;检索增强生成&#xff09;应用、AI 代理…...

白银6月想法

一、市场回顾 2025年5月&#xff0c;SHFE白银主力合约总体呈现出震荡偏强的运行格局。从2025年5月1日至2025年5月30日&#xff0c;白银期货价格整体运行在7944元至8342元区间内&#xff0c;最高价出现在5月22日的8342.0元&#xff0c;最低价则为5月15日的7944元。最终在5月30日…...