设计模式之命令模式:原理、实现与应用
引言
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。命令模式支持请求的排队、记录日志、撤销操作等功能。本文将深入探讨命令模式的原理、实现方式以及实际应用场景,帮助你更好地理解和使用这一设计模式。
1. 命令模式的核心概念
1.1 什么是命令模式?
命令模式是一种行为型设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。命令模式支持请求的排队、记录日志、撤销操作等功能。
1.2 命令模式的应用场景
-
请求排队:如任务队列、线程池等。
-
撤销操作:如文本编辑器中的撤销功能。
-
日志记录:如记录用户操作的日志。
-
事务处理:如数据库事务的提交和回滚。
2. 命令模式的实现方式
2.1 基本结构
命令模式通常包含以下几个角色:
-
命令接口(Command):定义执行操作的接口。
-
具体命令(Concrete Command):实现命令接口,封装具体的操作。
-
接收者(Receiver):执行命令的对象。
-
调用者(Invoker):持有命令对象,并调用命令的执行方法。
-
客户端(Client):创建命令对象并设置其接收者。
2.2 代码示例
// 命令接口
public interface Command {void execute();
}// 具体命令
public class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.action();}
}// 接收者
public class Receiver {public void action() {System.out.println("Receiver action");}
}// 调用者
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {command.execute();}
}// 客户端代码
public class Client {public static void main(String[] args) {Receiver receiver = new Receiver();Command command = new ConcreteCommand(receiver);Invoker invoker = new Invoker();invoker.setCommand(command);invoker.executeCommand();}
}
3. 命令模式的最佳实践
3.1 支持撤销操作
-
撤销操作:通过命令模式实现撤销操作,记录命令的执行状态。
-
重做操作:通过命令模式实现重做操作,记录命令的执行历史。
3.2 支持日志记录
-
日志记录:通过命令模式记录用户操作的日志,便于追踪和审计。
-
事务处理:通过命令模式实现事务的提交和回滚。
3.3 遵循单一职责原则
-
单一职责:每个命令只负责一个操作,保持职责单一。
-
高内聚低耦合:命令模式使得系统更加高内聚低耦合。
4. 命令模式的实际应用
4.1 文本编辑器
在文本编辑器中,命令模式用于实现撤销和重做功能。
// 命令接口
public interface TextCommand {void execute();void undo();
}// 具体命令
public class InsertTextCommand implements TextCommand {private StringBuilder text;private String insertedText;private int position;public InsertTextCommand(StringBuilder text, String insertedText, int position) {this.text = text;this.insertedText = insertedText;this.position = position;}@Overridepublic void execute() {text.insert(position, insertedText);}@Overridepublic void undo() {text.delete(position, position + insertedText.length());}
}// 调用者
public class TextEditor {private List<TextCommand> commandHistory = new ArrayList<>();private int currentCommandIndex = -1;public void executeCommand(TextCommand command) {command.execute();commandHistory.add(command);currentCommandIndex++;}public void undo() {if (currentCommandIndex >= 0) {TextCommand command = commandHistory.get(currentCommandIndex);command.undo();currentCommandIndex--;}}public void redo() {if (currentCommandIndex < commandHistory.size() - 1) {currentCommandIndex++;TextCommand command = commandHistory.get(currentCommandIndex);command.execute();}}
}// 客户端代码
public class Client {public static void main(String[] args) {StringBuilder text = new StringBuilder("Hello, World!");TextEditor editor = new TextEditor();TextCommand insertCommand = new InsertTextCommand(text, "Java ", 7);editor.executeCommand(insertCommand);System.out.println(text);editor.undo();System.out.println(text);editor.redo();System.out.println(text);}
}
4.2 任务队列
在任务队列中,命令模式用于实现任务的排队和执行。
// 命令接口
public interface Task {void execute();
}// 具体命令
public class PrintTask implements Task {private String message;public PrintTask(String message) {this.message = message;}@Overridepublic void execute() {System.out.println(message);}
}// 调用者
public class TaskQueue {private Queue<Task> tasks = new LinkedList<>();public void addTask(Task task) {tasks.add(task);}public void processTasks() {while (!tasks.isEmpty()) {Task task = tasks.poll();task.execute();}}
}// 客户端代码
public class Client {public static void main(String[] args) {TaskQueue queue = new TaskQueue();queue.addTask(new PrintTask("Task 1"));queue.addTask(new PrintTask("Task 2"));queue.addTask(new PrintTask("Task 3"));queue.processTasks();}
}
4.3 遥控器
在遥控器中,命令模式用于实现按钮与设备的解耦。
// 命令接口
public interface Command {void execute();
}// 具体命令
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 Light {public void on() {System.out.println("Light is on");}public void off() {System.out.println("Light is off");}
}// 调用者
public class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}
}// 客户端代码
public class Client {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.setCommand(lightOff);remote.pressButton();}
}
5. 命令模式的优缺点
5.1 优点
-
解耦:命令模式将请求的发送者与接收者解耦,使得请求的发送者无需知道具体的接收者。
-
扩展性:通过添加新的命令类,可以轻松扩展系统的功能。
-
支持撤销和重做:命令模式支持撤销和重做操作,提高了系统的灵活性。
5.2 缺点
-
类膨胀:如果系统中命令类过多,可能会导致类膨胀。
-
复杂性:命令模式增加了系统的复杂性,特别是在需要支持撤销和重做的情况下。
结语
命令模式是设计模式中用于封装请求的经典模式之一,适用于需要将请求的发送者与接收者解耦的场景。通过掌握命令模式的原理、实现方式以及最佳实践,你可以在实际开发中更好地应用这一模式。希望本文能为你的设计模式学习之旅提供一些实用的指导!
如果你有具体的需求或想要深入探讨某个主题,请告诉我,我可以进一步调整内容!
相关文章:
设计模式之命令模式:原理、实现与应用
引言 命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。命令模式支持请求的排队、记录日志、撤销操作等功能。本文将深入探讨命令模式的原理、实现方式以及实际应用…...
2025年十大AI工具对比
2025年十大AI工具对比 以下是2025年各大AI工具的详细对比,涵盖性能、功能、用户评价等方面,并以表格形式呈现。数据来源于多个权威来源,确保信息全面且准确。 对比表格 排名AI工具名称主要功能性能特点用户评价适用场景1DeepSeek多模态AI、…...
100道C#高频经典面试题及答案解析:C#程序员面试题库分类总结
分类一:C#基础语法 1. 值类型与引用类型的核心区别? 答案: 存储位置:值类型存栈/堆内联,引用类型存堆赋值方式:值类型复制内容,引用类型复制地址示例类型:int(值类型&…...
南京审计大学:《 面向工程审计行业的DeepSeek大模型应用指南》.pdf(免费下载)
大家好,我是吾鳴。 今天吾鳴要给大家分享的是由南京审计大学出品的《面向工程审计行业的DeepSeek大模型应用指南》,这份报告与《面向审计行业DeepSeek大模型操作指南》不同,这份报告更多的讲述DeepSeek怎么与工程审计行业结合,应该…...
DeepSeek AI大模型工作机制及未来方向
DeepSeek模型作为一款先进的人工智能模型,其工作原理结合了深度学习的前沿技术与工程优化策略,以下是其核心工作机制的分步解析: 1. 模型架构:基于Transformer的演进 - 核心结构:采用多层Transformer解码器堆叠&am…...
第十七章:Future Directions_《C++ Templates》notes
Future Directions 核心重难点:示例代码: 设计题多选题答案设计题详解 核心重难点: 泛型非类型模板参数 允许任意类型作为非类型模板参数(如template<typename T, auto N>)需解决类型推导和链接问题 编译期控制…...
NVIDIA Dynamo源码编译
Ref https://github.com/PyO3/maturin Rust 程序设计语言 代码库: https://github.com/ai-dynamo/dynamo https://github.com/ai-dynamo/nixl dynamo/container/Dockerfile.vllm 相关whl包 官方提供了4个whl包 ai_dynamo # 这个包ubuntu 22.04也可以用&…...
【前端】Canvas画布实现在线的唇膏换色功能
【前端】Canvas画布实现在线的唇膏换色功能 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 【前端】Canvas画布实现在线的唇膏换色功能背景概述以下是我们的实现方法!第一步 — 找…...
arcgispro加载在线地图
World_Imagery (MapServer)https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer添加arcgis server WMTS 服务 by xdcxdc.at xdc的个人站点。博客请转至 http://i.xdc.at/ http://xdc.at/map/wmts 添加WMTS服务器...
华为网路设备学习-16 虚拟路由器冗余协议(VRRP)
VRRP是针对干线上三层网络设备(如:路由器、防火墙等)的网络虚拟化技术,提供冗余和状态监测等功能。确保在网络中的单点故障发生时,能够快速切换到备份设备,从而保证网络通信的连续性和可靠性。 VRRP通过…...
使用请求调用本地部署的stable-diffusion接口
stable-diffusion-webui项目地址 具体部署教程请去B站寻找或者直接使用整合包 这里直接编写工具类 public class StableDiffusionUtil {private static final String BASE_URL "http://127.0.0.1:7860";private static final OkHttpClient CLIENT new OkHttpClien…...
封装一个分割线组件
最终样式 Vue2代码 <template><div class"sep-line"><div class"sep-label"><span class"sep-box-text"><slot>{{ title }}</slot> <!-- 默认插槽内容,如果没有传递内容则使用title -->&…...
网络HTTPS协议
Https HTTPS(Hypertext Transfer Protocol Secure)是 HTTP 协议的加密版本,它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说: • 加密通信:在用户请求访问一个 HTTPS 网站时,客户端&#x…...
CMake 函数和宏
CMake 函数 CMake 函数定义语法如下, 其中 name 为函数名, <arg1> 为参数名, <commands> 为函数体. 函数定义后, 可以通过 name 调用函数. 函数名允许字母数字下划线, 不区分大小写. function(name [<arg1> ...])<commands> endfunction()如下的样例…...
OSASIS(One-Shot Structure-Aware Stylized Image Synthesis)
文章目录 摘要abstract论文摘要方法损失函数实验结论 总结 摘要 本周阅读了一篇关于新型图像风格化的论文《One-Shot Structure-Aware Stylized Image Synthesis》,旨在解决现有GAN模型在风格化过程中难以保持输入图像结构的问题。通过分离图像的结构和语义信息&am…...
C++学习之网盘项目单例模式
目录 1.知识点概述 2.单例介绍 3.单例饿汉模式 4.饿汉模式四个版本 5.单例类的使用 6.关于token的作用和存储 7.样式表使用方法 8.qss文件中选择器介绍 9.qss文件样式讲解和测试 10.qss美化登录界面补充 11.QHTTPMULTIPART类的使用 12.文件上传协议 13.文件上传协议…...
Leetcode—15. 三数之和(哈希表—基础算法)
题目: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的…...
Apache Flink技术原理深入解析:任务执行流程全景图
前言 本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见大数据技术体系 思维导图 📌 引言 Apache Flink 作为一款高性能的分布式流处理引擎,其内部执行机制精妙而复杂。本文将…...
DeepBI:重构流量逻辑,助力亚马逊广告实现高效流量增长
在日益激烈的跨境电商竞争环境中,广告投放早已从“粗放撒网”走向“精细化运营”。尤其是在亚马逊这样一个成熟且竞争白热化的平台,如何在广告预算有限的前提下实现高效曝光、精准触达、稳定转化,成为众多卖家和运营团队面临的核心挑战。 De…...
RAG(Retrieval-Augmented Generation)基建之PDF解析的“魔法”与“陷阱”
嘿,亲爱的算法工程师们!今天咱们聊一聊PDF解析的那些事儿,简直就像是在玩一场“信息捉迷藏”游戏!PDF文档就像是个调皮的小精灵,表面上看起来规规矩矩,但当你想要从它那里提取信息时,它就开始跟…...
C语言【文件操作】详解中(会使用fgetc,fputc,fgets,fputs,fscanf,fprintf,fread,fwrite函数)
引言 介绍和文件操作中文件的顺序读写相关的函数 看这篇博文前,希望您先仔细看一下这篇博文,理解一下文件指针和流的概念:C语言【文件操作】详解上-CSDN博客文章浏览阅读606次,点赞26次,收藏4次。先整体认识一下文件是…...
【Python Cookbook】字符串和文本(一)
字符串和文本(一) 1.使用多个界定符分割字符串2.字符串开头或结尾匹配3.用 Shell 通配符匹配字符串4.字符串匹配和搜索5.字符串搜索和替换 1.使用多个界定符分割字符串 你需要将一个字符串分割为多个字段,但是分隔符(还有周围的空…...
GpuGeek:破解算力难题,赋能AI创新与普及
文章目录 一、引言二、填补算力资源供需缺口,降低使用门槛三、提升算力资源利用率,推动高效协作四、满足多样化需求,支持AI技术落地五、推动算力市场创新,促进生态良性发展六、助力AI人才培养,推动行业长远发展七、结语…...
扣子平台知识库不能上传成功
扣子平台知识库不能上传成功 目录 扣子平台知识库不能上传成功查看模板复制头部到自己的excel中json数据转为excel或者csv(一定使用excel,csv总是报错) 查看模板复制头部到自己的excel中 json数据转为excel或者csv(一定使用excel&…...
蓝桥杯 R格式
问题描述 小蓝最近在研究一种浮点数的表示方法:R 格式。 对于一个大于 0 的浮点数 d,可以用 R 格式的整数来表示。 给定一个转换参数 n,将浮点数转换为 R 格式整数的做法是: 将浮点数乘以 2^n;将结果四舍五入到最接…...
计算机视觉的多模态模型
计算机视觉的多模态模型 是指能够同时处理和理解 多种类型数据(模态) 的模型。这些模态可以包括图像、文本、音频、视频、深度信息等。多模态模型的核心目标是利用不同模态之间的互补信息,提升模型的性能和泛化能力。 1. 多模态模型的核心思想…...
JVM的组成--运行时数据区
JVM的组成 1、类加载器(ClassLoader) 类加载器负责将字节码文件从文件系统中加载到JVM中,分为:加载、链接(验证、准备、解析)、和初始化三个阶段 2、运行时数据区 运行时数据区包括:程序计数…...
c++进阶之------红黑树
一、概念 红黑树(Red-Black Tree)是一种自平衡二叉查找树,它在计算机科学的许多领域中都有广泛应用,比如Java中的TreeMap和C中的set/map等数据结构的底层实现。红黑树通过在每个节点上增加一个颜色属性(红色或黑色&am…...
《鸿蒙原生应用开发:掌控Ability生命周期的艺术》
在鸿蒙原生应用开发的广袤天地中,Ability作为构建应用的基本单元,其生命周期的有效管理宛如基石之于高楼,是打造稳定、高效且用户体验卓越应用的关键所在。随着鸿蒙生态的蓬勃发展,深入理解并巧妙运用Ability生命周期,…...
ubuntu22.04安装搜狗输入法保姆教程~
一、添加中文语言支持 1.首先打开设置,找到Language and Region 2.点击Manage Installed Languages 3.点击 Install/Remove Languages... 4.选中Chinese (simplified),点击Apply...
