设计模式 行为型 命令模式(Command Pattern)与 常见技术框架应用 解析

命令模式(Command Pattern)是一种行为型设计模式,它旨在将请求发送者和接收者解耦,通过将一个请求封装为一个对象,从而允许参数化客户端对象以进行不同的请求、排队请求或记录请求,并支持可撤销操作。
在软件开发中,经常会遇到需要将操作请求和操作的具体实现相分离的场景。比如在一个图形编辑软件里,用户可能执行绘制图形、移动图形、删除图形等多种操作。如果将这些操作的发起和具体执行逻辑紧密耦合在一起,会使代码的可维护性和扩展性变差。命令模式就是为了解决这类问题而诞生的,它把对操作的请求封装成独立的对象,使得我们可以像处理其他数据一样来处理这些操作请求。
一、核心思想
命令模式的核心在于将一个请求(命令)封装为一个对象。这样做的好处是可以将请求参数化,方便对请求进行存储、传递、调用、排队、记录日志以及支持撤销和重做等操作。通过这种方式,把发出命令的责任和执行命令的责任分割开,降低了系统模块之间的耦合度。
二、定义与结构
- 定义:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。
- 结构
- Command(命令):这是一个抽象类或接口,声明了执行操作的抽象方法execute()。
- ConcreteCommand(具体命令):实现了Command接口,它知道具体的接收者对象,并在execute方法中调用接收者的相应操作方法。
- Receiver(接收者):负责执行命令所要求的具体操作,它包含了真正实现业务逻辑的代码。
- Invoker(调用者):负责调用命令对象执行请求,它持有一个命令对象的引用,通过调用命令对象的execute方法来触发操作。
三、角色
- 命令(Command):为所有具体命令类定义了统一的接口,使得调用者可以统一地调用命令的执行方法。
- 具体命令(ConcreteCommand):将一个接收者对象和一个动作绑定,在执行execute方法时,调用接收者的相应动作。
- 接收者(Receiver):知晓如何执行与请求相关的具体操作,是命令真正的执行者。
- 调用者(Invoker):负责安排命令的执行,它并不关心命令的具体实现,只关心如何触发命令的执行。
四、实现步骤及代码示例
- 定义命令接口
public interface Command {void execute();
}
- 定义接收者类
public class Light {public void on() {System.out.println("Light is on");}public void off() {System.out.println("Light is off");}
}
- 定义具体命令类
public class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}
}public class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}
}
- 定义调用者类
public class RemoteControl {private Command command;public RemoteControl(Command command) {this.command = command;}public void pressButton() {command.execute();}
}
- 测试代码
public class Main {public static void main(String[] args) {Light light = new Light();Command lightOnCommand = new LightOnCommand(light);Command lightOffCommand = new LightOffCommand(light);RemoteControl onRemote = new RemoteControl(lightOnCommand);RemoteControl offRemote = new RemoteControl(lightOffCommand);onRemote.pressButton();offRemote.pressButton();}
}
五、常见技术框架应用
JavaScript 实现命令模式:
// 接收者
function Door() {this.open = function () {console.log('Door is opened');};this.close = function () {console.log('Door is closed');};
}// 命令接口
function Command(door) {this.door = door;
}// 具体命令
function OpenDoorCommand(door) {Command.call(this, door);this.execute = function () {this.door.open();};
}function CloseDoorCommand(door) {Command.call(this, door);this.execute = function () {this.door.close();};
}// 调用者
function Remote(door) {this.command = null;this.setCommand = function (command) {this.command = command;};this.pressButton = function () {if (this.command) {this.command.execute();}};
}// 使用示例
let door = new Door();
let openCommand = new OpenDoorCommand(door);
let closeCommand = new CloseDoorCommand(door);let remote = new Remote(door);
remote.setCommand(openCommand);
remote.pressButton();remote.setCommand(closeCommand);
remote.pressButton();
六、应用场景
当你需要在不同的时刻指定、排列和执行请求的时候。
当你需要支持命令的撤销(Undo)功能时。
当你需要将请求作为对象进行传递和操作时。
当你需要组合多个操作形成宏命令时。
- 遥控器控制:如上面的示例所示,可以用命令模式实现遥控器来控制不同的家电设备,如电视、音响和灯。
- 文本编辑器操作:文本编辑器中的撤销、重做、剪切、复制、粘贴等操作可以使用命令模式来实现。
- 菜单系统:图形用户界面(GUI)应用中的菜单项和按钮操作可以通过命令模式来处理。
- 游戏中的动作:在游戏中,角色的动作和命令(如攻击、防御、跳跃等)可以使用命令模式来处理。
- 多级撤销操作:命令模式支持撤销和重做操作,因此在需要多级撤销的应用中很有用,如图像编辑器或CAD软件。
- 日程安排应用:在日程安排应用中,可以使用命令模式来处理添加、编辑、删除事件等操作。
七、优缺点
优点
- 解耦调用者和接收者:调用者和接收者之间通过命令对象进行交互,调用者无需了解接收者的具体实现细节,降低了模块之间的耦合度。
- 支持命令的扩展和组合:可以很方便地定义新的命令类,也可以将多个命令组合成一个复合命令,以实现更复杂的功能。
- 便于实现撤销和重做:通过在命令对象中保存操作的相关状态信息,可以很方便地实现操作的撤销和重做功能。
缺点
- 增加系统复杂度:由于引入了命令对象和相关的类,会增加系统的类和对象数量,导致系统复杂度上升,尤其是在命令种类繁多的情况下。
- 性能开销:命令的封装和传递会带来一定的性能开销,在对性能要求极高的场景下,需要谨慎评估是否适合使用命令模式。

相关文章:
设计模式 行为型 命令模式(Command Pattern)与 常见技术框架应用 解析
命令模式(Command Pattern)是一种行为型设计模式,它旨在将请求发送者和接收者解耦,通过将一个请求封装为一个对象,从而允许参数化客户端对象以进行不同的请求、排队请求或记录请求,并支持可撤销操作。 在软…...
【Redis】简介|优点|使用场景|为什么Redis快
目录 一、简介 二、特性(优点) 三、使用场景 一、简介 内存中存储数据的中间件,用于数据库,数据缓存,在分布式系统中能够大展拳脚 中间件:应用程序可以直接从 Redis 中获取数据,而不必频繁地…...
Clisoft SOS与CAD系统集成
Clisoft SOS与CAD系统集成 以下内容大部分来自官方文档,目前只用到与Cadence Virtuoso集成,其他还未用到,如有问题或相关建议,可以留言。 与Keysight ADS集成 更新SOS客户端配置文件sos.cfg,以包含支持ADS的模板&am…...
【linux系统之redis6】redis的安装与初始化
下载redis的linux对应的安装包,并上传到linux虚拟机里面 解压压缩包 tar -zxzf redis-6.2.6.tar.gz解压后,进入redis文件 cd redis-6.2.6执行编译 make && make install看到下图,就说明redis安装成功了 默认的安装路径,…...
Backend - EF Core(C# 操作数据库 DB)
目录 一、EF Core 1. 使用的ORM框架(对象关系映射) 2. EFCore 常见两种模式 3. EFCore 提供程序 二、 EF 操作数据库(Code First) 1. 下载NuGet插件 2.创建模型类文件 3.创建DBContext文件 4.Programs.cs文件 5.appsettings.Devel…...
WebSocket 性能优化:从理论到实践
在前四篇文章中,我们深入探讨了 WebSocket 的基础原理、服务端开发、客户端实现和安全实践。今天,让我们把重点放在性能优化上,看看如何构建一个高性能的 WebSocket 应用。我曾在一个直播平台项目中,通过一系列优化措施,将单台服务器的并发连接数从 1 万提升到 10 万。 性能挑…...
我用AI学Android Jetpack Compose之入门篇(2)
我跑成功了第一个Compose应用,但我还是有很多疑问,请人工智能来解释一下吧。答案来自 通义千问 文章目录 1.请解释一下Compose项目的目录结构。根目录模块目录(通常是app)app/build.gradleapp/src/mainapp/src/main/uiapp/src/ma…...
以太网协议在汽车应用中的动与静
为了让网络中的设备能够随时或随地接入网络或离开网络,做到:接入时无需多余的配置就能和其他设备互相通信;离开时又不会导致设备或网络崩溃。以太网从物理层到协议层展现出多方面的灵活性,,使其成为连接各种设备和系统…...
【C语言】_指针与数组
目录 1. 数组名的含义 1.1 数组名与数组首元素的地址的联系 1.3 数组名与首元素地址相异的情况 2. 使用指针访问数组 3. 一维数组传参的本质 3.1 代码示例1:函数体内计算sz(sz不作实参传递) 3.2 代码示例2:sz作为实参传递 3…...
Selenium 的四种等待方式及使用场景
Selenium 的四种等待方式及使用场景 隐式等待(Implicit Wait)显式等待(Explicit Wait)自定义等待(Custom Wait)固定等待(Sleep) 1. 隐式等待 定义: 隐式等待是为 WebD…...
React知识盲点——组件通信、性能优化、高级功能详解(大纲)
组件通信 React 组件通信详解 在 React 中,组件通信是一个核心概念,主要指的是如何让不同的组件共享和传递数据。React 提供了多种机制来实现组件间的数据传递和状态共享。以下是几种常见的组件通信方式,包括:父子组件通信&…...
Vue 按键生成多个表单
本文通过 vueele,通过循环ref的方法生成多个表单,代码如下: <template><div><el-button click"addText" style"margin: 15px 0; ">添加字段</el-button><div v-for"item, index in dataList"…...
网络安全:交换机技术
单播,组播广播 单播(unicast): 是指封包在计算机网络的传输中,目的地址为单一目标的一种传输方式。它是现今网络应用最为广泛,通常所使用的网络协议或服务大多采用单播传输,例如一切基于TCP的协议。组播(multicast): 也叫多播&am…...
Flask 快速入门
1. Flask 简介 1.1 什么是 Flask Flask 是一个用 Python 编写的轻量级 Web 框架,被誉为 微框架。它提供基础功能,如路由、请求处理和模板引擎,但不强迫开发者使用特定库或工具,赋予开发人员高度的自由选择权,以满足不…...
C#设计模式(行为型模式):备忘录模式,时光倒流的魔法
C#设计模式:备忘录模式,时光倒流的魔法 在软件开发中,我们经常会遇到需要保存对象状态,并在未来某个时刻恢复的场景。例如: 撤销操作: 文本编辑器中的撤销功能,游戏中的回退操作。事务回滚&am…...
数据库高安全—角色权限:权限管理权限检查
目录 3.3 权限管理 3.4 权限检查 书接上文数据库高安全—角色权限:角色创建角色管理,从角色创建和角色管理两方面对高斯数据库的角色权限进行了介绍,本篇将从权限管理和权限检查方面继续解读高斯数据库的角色权限。 3.3 权限管理 &#x…...
FastAPI 的依赖注入与生命周期管理深度解析
FastAPI 的依赖注入与生命周期管理深度解析 目录 🔧 依赖注入与 FastAPI 高级特性 1.1 依赖注入的基础与核心概念1.2 FastAPI 的依赖注入机制与设计理念1.3 FastAPI 依赖注入的异步特性 🕹 生命周期与依赖的异步管理 2.1 依赖的生命周期管理࿱…...
【express-generator】05-路由中间件和错误处理(第一阶段收尾)
一、前言 上篇文章我们介绍了express-generator的请求体解析,重点讲了常用的请求体数据格式(JSON/URL 编码的表单数据)以及一个FILE文件上传,同时搭配代码示范进行辅助理解。 二、本篇重点 我们继续第一阶段的知识,…...
Linux环境下确认并操作 Git 仓库
在软件开发和版本控制中,Git 已成为不可或缺的工具。有时,我们需要确认某个目录是否是一个 Git 仓库,并在该目录中运行脚本。本文将详细介绍如何确认 /usr/local/src/zcxt/backend/policy-system-backend 目录是否是一个 Git 仓库,…...
UDP -- 简易聊天室
目录 gitee(内有详细代码) 图解 MessageRoute.hpp UdpClient.hpp UdpServer.hpp Main.hpp 运行结果(本地通信) 如何分开对话显示? gitee(内有详细代码) chat_room zihuixie/Linux_Lear…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...
英国云服务器上安装宝塔面板(BT Panel)
在英国云服务器上安装宝塔面板(BT Panel) 是完全可行的,尤其适合需要远程管理Linux服务器、快速部署网站、数据库、FTP、SSL证书等服务的用户。宝塔面板以其可视化操作界面和强大的功能广受国内用户欢迎,虽然官方主要面向中国大陆…...
