命令模式的理解和实践

        在软件开发中,设计模式是开发者们经过长期实践总结出来的、可复用的解决方案,用于解决常见的设计问题。命令模式(Command Pattern)是行为型设计模式之一,它通过将一个请求封装成一个对象,从而允许用户用不同的请求对客户端进行参数化、对请求进行排队或者记录请求日志,以及支持可撤销的操作。本文将详细讲解命令模式的概念、原理、优点,并通过Java语言进行实践。

一、命令模式的概念

        命令模式的核心思想是将一个请求封装成一个对象,从而允许你使用不同的请求、队列请求、记录请求日志,以及支持可撤销的操作。命令模式将发出请求的对象(调用者)和执行请求的对象(接收者)解耦,使得请求可以通过不同的请求对象进行参数化、排队或记录。

        命令模式主要包含以下几个角色:

  1. 命令接口(Command):声明一个执行操作的接口。
  2. 具体命令类(ConcreteCommand):实现命令接口,将接收者对象绑定到具体的操作上,并调用接收者的方法来执行操作。
  3. 接收者类(Receiver):知道如何执行具体的操作,任何类都可以作为接收者。
  4. 调用者(Invoker):要求命令对象执行请求,它持有一个命令对象的引用。
  5. 客户端(Client):创建具体的命令对象,并设置命令对象的接收者。

二、命令模式的原理

        命令模式的原理在于将请求封装成对象,使得请求可以被存储、传递、序列化和执行。通过引入命令对象,调用者和接收者之间的依赖关系被解耦,调用者不再直接调用接收者的方法,而是通过命令对象来间接调用。

        具体来说,命令模式的原理包括以下几个步骤:

  1. 创建命令接口:定义一个通用的命令接口,声明一个执行操作的 execute() 方法。
  2. 实现具体命令类:针对每个具体的操作,创建一个实现命令接口的具体命令类。具体命令类持有一个接收者对象的引用,并在 execute() 方法中调用接收者的方法来执行操作。
  3. 创建接收者类:接收者类知道如何执行具体的操作,它包含了执行操作的方法。
  4. 创建调用者:调用者持有一个命令对象的引用,它可以在适当的时候调用命令对象的 execute() 方法来执行操作。调用者不需要知道具体的命令对象和接收者对象,它只需要知道命令接口。
  5. 客户端创建命令对象:客户端在需要执行某个操作时,创建具体的命令对象,并将接收者对象传递给命令对象。然后,客户端将命令对象传递给调用者,调用者会在适当的时候执行命令。

三、命令模式的优点

        命令模式具有以下几个优点:

  1. 解耦请求与实现:命令模式将请求与实现解耦,使得请求可以通过不同的命令对象进行参数化、排队或记录。
  2. 灵活性:由于命令对象可以被存储、传递和序列化,因此命令模式提供了更大的灵活性。例如,可以将命令对象存储在一个队列中,然后依次执行队列中的命令。
  3. 扩展性:命令模式易于扩展新的命令,只需添加新的具体命令类即可,无需修改现有的代码。
  4. 支持撤销操作:通过实现一个撤销操作的接口,命令模式可以支持撤销操作。

四、命令模式的实践

        下面,我们将通过Java语言来实现一个简单的命令模式示例。假设我们有一个简单的图形用户界面(GUI)应用程序,其中有几个按钮,每个按钮对应不同的操作,比如打开文件、保存文件和退出程序。我们可以使用命令模式来将这些操作封装成命令对象,从而简化按钮和操作的关联。

1. 创建命令接口

        首先,我们定义一个通用的命令接口 Command,它包含一个 execute() 方法。

// 命令接口
public interface Command {void execute();
}


2. 创建具体命令类

        接下来,我们针对每个具体的操作创建实现命令接口的具体命令类。例如,我们创建 OpenFileCommandSaveFileCommand 和 ExitCommand 三个具体命令类。

// 打开文件命令
public class OpenFileCommand implements Command {private Receiver receiver;public OpenFileCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.openFile();}
}// 保存文件命令
public class SaveFileCommand implements Command {private Receiver receiver;public SaveFileCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.saveFile();}
}// 退出命令
public class ExitCommand implements Command {private Receiver receiver;public ExitCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.exit();}
}


3. 创建接收者类

        然后,我们创建一个接收者类 Receiver,它包含执行具体操作的方法。

// 接收者类
public class Receiver {public void openFile() {System.out.println("File opened.");}public void saveFile() {System.out.println("File saved.");}public void exit() {System.out.println("Application exited.");}
}


4. 创建调用者

        接下来,我们创建一个调用者类 Invoker,它持有一个命令对象的引用,并可以在适当的时候调用命令对象的 execute() 方法。

// 调用者
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {if (command != null) {command.execute();}}
}


5. 客户端创建命令对象

        最后,我们在客户端代码中创建具体的命令对象,并将接收者对象传递给命令对象。然后,将命令对象传递给调用者,并在适当的时候执行命令。

// 客户端代码
public class Client {public static void main(String[] args) {// 创建接收者对象Receiver receiver = new Receiver();// 创建命令对象Command openFileCommand = new OpenFileCommand(receiver);Command saveFileCommand = new SaveFileCommand(receiver);Command exitCommand = new ExitCommand(receiver);// 创建调用者对象Invoker invoker = new Invoker();// 设置命令并执行invoker.setCommand(openFileCommand);invoker.executeCommand();invoker.setCommand(saveFileCommand);invoker.executeCommand();invoker.setCommand(exitCommand);invoker.executeCommand();}
}


        运行客户端代码,输出如下:

File opened.
File saved.
Application exited.


总结

        命令模式是一种强大的行为型设计模式,它通过将一个请求封装成一个对象,使得请求可以被存储、传递、序列化和执行。命令模式将发出请求的对象(调用者)和执行请求的对象(接收者)解耦,使得请求可以通过不同的命令对象进行参数化、排队或记录。命令模式具有解耦请求与实现、灵活性、扩展性和支持撤销操作等优点。通过本文的讲解和实践,相信读者对命令模式有了更深入的理解,并能够在实际开发中灵活运用该模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/63670.shtml

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

相关文章

SpringBoot3整合SpringMVC

一、实现过程: (1).创建程序 (2).引入依赖: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"…

【优选算法篇】剥洋葱式探索:用二分查找精准定位答案(下篇)

文章目录 须知 &#x1f4ac; 欢迎讨论&#xff1a;如果你在学习过程中有任何问题或想法&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习。你的支持是我继续创作的动力&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;觉得这篇文章对你有帮助吗&#xff1…

若依集成更好用的easyexcel

背景 若依使用的是apach poi并在此基础上进行封装apach poi的原生的api是很复杂的&#xff0c;若依简化了了此操作apach poi的上传速率和下载速率都是没有优化的&#xff0c;依赖于文件大小的限制在此前提下&#xff0c;如果没法满足客户的需求&#xff08;超大型文件的上传&am…

在Ubuntu上使用docker compose安装N卡GPU的Ollama服务

在现代计算环境中,利用 GPU 进行计算加速变得越来越重要。下面将讲解如何在Ubuntu上使用docker compose安装N卡GPU的Ollama服务。 1、安装 NVIDIA 容器工具 首先,需要确保你的系统已经安装了 NVIDIA 容器工具 nvidia-container-toolkit。这是让 Docker 容器访问 GPU 的关键…

MySQL语句学习第三篇_数据库

MySQL语句学习第三篇_数据库 专栏记录MySQL的学习&#xff0c;感谢大家观看。 本章的专栏&#x1f4da;➡️MySQL语法学习 本博客前一章节指向➡️MySQL语句学习第二篇 本人的博客➡️:如烟花般绚烂却又稍纵即逝的主页 文章目录 MySQL的基础操作&#xff08;改与查&#xff0…

windows将文件推给Android真机/实机

记录一下 因为以前只试过从真机实机中将文件推给windows 但是从windows只简单复制粘贴的话会一直报错。 1.电脑安装adb 2.手机开启开发者模式 usb调试 3.usb连接选择文件传输 4.推送命令adb push 文件路径 /sdcard/download 步骤1和2和3不作赘述&#xff0c;可以搜相关配置教程…

C语言——验证“哥德巴赫猜想”

问题描述&#xff1a; 验证"哥德巴赫猜想" 任何一个大于2的偶数都可以表示为两个质数之和。例如&#xff0c;4可以表示为22&#xff0c;6可以表示为33&#xff0c;8可以表示为35等 //验证"哥德巴赫猜想" //任何一个大于2的偶数都可以表示为两个质数之和…

利用 360 安全卫士极速版关闭电脑开机自启动软件教程

在使用电脑的过程中&#xff0c;过多的开机自启动软件会严重拖慢电脑的开机速度&#xff0c;影响我们的使用体验。本教程中简鹿办公将详细介绍如何使用 360 安全卫士极速版关闭电脑开机自启动软件&#xff0c;让您的电脑开机更加迅速流畅。 一、打开 360 安全卫士极速版 在电…

分布式搜索引擎之elasticsearch基本使用2

分布式搜索引擎之elasticsearch基本使用2 在分布式搜索引擎之elasticsearch基本使用1中&#xff0c;我们已经导入了大量数据到elasticsearch中&#xff0c;实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以j接下来&#xff0c;我们研究下…

[ACTF2020 新生赛]Include

感觉毫无头绪e一下&#xff0c;发现要使用伪协议 伪协议&#xff1a;是PHP自己支持的一种协议与封装协议&#xff0c;简单说就是PHP定义的一种特殊访问资源的方法。 2.什么时候用PHP伪协议? 可能遇到的文件包含函数&#xff1a; 1、include 2、require 3、include_once 4、r…

vue3使用Eachart图表库踩坑记录

前言 大家好我是没钱的君子下流坯&#xff0c;用自己的话解释自己的知识。很久很更新了&#xff0c;最近一直在加班&#xff0c;今天记录一个eachar图表报警告说过去不到当前DOM节点的宽高导致页面中的图表宽高不正确的坑。 案例 就是一些基础的图形的使用&#xff0c;一个后…

【系统架构核心服务设计】使用 Redis ZSET 实现排行榜服务

目录 一、排行榜的应用场景 二、排行榜技术的特点 三、使用Redis ZSET实现排行榜 3.1 引入依赖 3.2 配置Redis连接 3.3 创建实体类&#xff08;可选&#xff09; 3.4 编写 Redis 操作服务层 3.5 编写控制器层 3.6 测试 3.6.1 测试 addMovieScore 接口 3.6.2 测试 g…

架构15-服务网格

零、文章目录 架构15-服务网格 1、透明通信的涅槃 &#xff08;1&#xff09;服务网格 概念 服务网格是一种处理程序间通信的基础设施&#xff0c;主要由数据平面和控制平面组成。它通过边车代理和控制程序管理程序间的通信&#xff0c;弥补了容器编排系统对分布式应用细粒…

constexpr、const和 #define 的比较

constexpr、const 和 #define 的比较 一、定义常量 constexpr 定义&#xff1a;constexpr用于定义在编译期可求值的常量表达式。示例&#xff1a;constexpr int x 5;这里&#xff0c;x的值在编译期就确定为5。 const 定义&#xff1a;const表示变量在运行期间不能被修改&…

C# RSA加密和解密,RSA生成私钥和公钥

C# RSA加密和解密&#xff0c;RSA生成私钥和公钥&#xff08;使用XML格式秘钥&#xff09; 目录 前言生成xml格式的公钥和私钥 PrivateKeyPublicKey测试加密、解密 方案1&#xff1a;RSA公钥加密&#xff0c;RSA私钥解密方案2&#xff1a;RSA私钥加密&#xff0c;RSA私钥解密…

Linux命令进阶·软链接命令(ln)、查看系统时间命令(date)、自动校准系统时间程序(ntp)

目录 1. 软链接——ln命令 2. 查看系统时间——date命令 3. 自动校准系统时间——ntp程序 1. 软链接——ln命令 在系统中创建软链接&#xff0c;可以将文件、文件夹链接到其他位置。作用相当于windows中的快捷方式。 语法&#xff1a;ln -s 参数1 参数2 -s选项&#xff…

NanoLog起步笔记-7-log解压过程初探

nonolog起步笔记-6-log解压过程初探 再看解压过程建立调试工程修改makefile添加新的launch项 注&#xff1a;重新学习nanolog的README.mdPost-Execution Log Decompressor 下面我们尝试了解&#xff0c;解压的过程&#xff0c;是如何得到文件头部的meta信息的。 再看解压过程 …

人工智能大模型LLM开源资源汇总(持续更新)

说明 目前是大范围整理阶段&#xff0c;所以存在大量机翻说明&#xff0c;后续会逐渐补充和完善资料&#xff0c;减少机翻并增加说明。 Github上的汇总资源&#xff08;大部分英文&#xff09; awesome-production-machine-learning 此存储库包含一系列精选的优秀开源库&am…

C++实现排序算法:冒泡排序

目录 前言 冒泡排序性质 C代码实现冒泡排序 冒泡图解 第一趟排序 第二趟排序 第三趟排序 排序结果 结语 前言 冒泡排序的基本思想是通过从前往后&#xff08;从后往前&#xff09;两两比较&#xff0c;若为逆序&#xff08;即arr[i] < arr[i 1]&#xff09;则交换…

中介者模式的理解和实践

一、中介者模式概述 中介者模式&#xff08;Mediator Pattern&#xff09;&#xff0c;也称为调解者模式或调停者模式&#xff0c;是一种行为设计模式。它的核心思想是通过引入一个中介者对象来封装一系列对象之间的交互&#xff0c;使得这些对象不必直接相互作用&#xff0c;从…