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

设计模式详解(十九)——命令模式

命令模式简介

命令模式定义
命令模式(Command Pattern)是一种在面向对象程序设计中常用的行为型设计模式。命令模式的核心思想在于将请求封装成一个对象,从而使发出请求的责任和执行请求的责任分割开。它可以让请求发送者和请求接收者之间消除彼此之间的耦合关系。这种模式的关键在于将请求的行为参数化,使得不同的请求可以在不同时间由不同的对象来处理。同时,它支持对请求排队、记录请求日志,以及实现可撤销的操作。

命令模式包含以下角色:

  1. 命令角色(Command):这是一个抽象类或接口,它定义了执行命令的方法,通常包含执行(execute)方法,但不实现具体的命令行为。
  2. 具体命令角色(Concrete Command):实现了命令接口,持有接收者的引用,并在执行方法中调用接收者的方法来执行具体的命令行为;实现execute()方法,负责调用接收者的相应操作。
  3. 接收者角色(Receiver):接收者是执行命令的对象,它实现了命令所需要执行的具体操作。接收者可以有多个,每个接收者都可以执行不同的操作。
  4. 请求者角色(Invoker):请求者持有命令对象的引用,并通过调用命令的execute()方法来执行请求。它不需要知道命令的具体实现细节,只需知道如何调用命令对象。负责调用命令对象执行请求,相关的方法叫做行动方法(如action())。
  5. 客户端(Client):创建具体命令对象并设置其接收者,将命令对象传递给调用者执行请求。

命令模式优缺点:
优点:

  1. 解耦合:命令模式降低了调用者和接收者之间的耦合度。调用者只需知道命令的接口,而不需要知道命令的具体实现细节,从而降低系统的耦合度。
  2. 可扩展性:新的命令可以很容易地添加到系统中,而无需修改现有的代码结构,从而不影响现有的命令,符合开闭原则。
  3. 支持撤销和重做:由于命令被封装成对象,在具体命令类中保存状态,可以轻松地实现命令的撤销和重做功能。
  4. 日志记录:可以在命令对象中增加日志记录功能,记录命令的执行情况。这对于系统的调试和审计非常有帮助。
  5. 容易实现队列和宏命令:可以创建宏命令(复合命令),即把多个简单命令组合成一个更复杂的命令。
  6. 更好的安全性:命令模式可以帮助限制对敏感方法的访问权限,因为命令接口可以隐藏这些方法的实现细节。

缺点:

  1. 过多的具体命令类:每个具体命令都需要一个单独的类,可能会导致类的数量增加。如果系统中的命令种类非常多,可能会导致产生大量的具体命令类
  2. 系统复杂性:引入了额外的类和对象,增加了系统的复杂性。
  3. 执行效率:由于命令被封装成对象,可能会导致执行效率略有降低,特别是在需要大量命令对象的情况下。
  4. 可能增加对象数量:为了支持撤销操作,每个命令可能需要保存额外的状态信息,这会增加对象的数量。

使用场景

  1. 撤销和重做操作:当需要支持撤销和重做操作时,可以使用命令模式将每个操作封装成一个命令对象,从而实现撤销和重做功能。
  2. 队列请求:当需要将请求排队、记录请求日志、支持事务等场景时,可以使用命令模式将请求封装成命令对象,然后由调用者依次执行这些命令对象。
  3. 宏命令:当需要将多个简单命令组合成一个复合命令时,可以使用命令模式。
  4. 远程控制和自动化:在远程控制系统中,可以使用命令模式来发送远程指令给接收设备。
  5. 日程安排系统:在日程安排系统中,可以使用命令模式实现对日程的增加、删除、修改等操作,支持撤销和重做功能。
  6. GUI 应用程序:在图形用户界面中,命令模式可以用来处理用户的输入事件,例如按钮点击、菜单选项选择等
  7. 日志记录和历史追踪:命令模式可以用来记录操作的历史,这对于审计和调试非常有用。

以下举一个命令模式的例子:
下面通过一个简单的例子来演示。
假如我们自己开发一个音乐播放器,有播放功能、切换上一首功能、切换下一首功能、暂停功能,我们自己去操作的时候并不是直接调用音乐播放器的方法,而是通过一个控制条去传达指令给播放器内部。那么每个按钮就相当于是对一条命令的封装。

创建接收者角色(Receiver)

/*** 音乐播放器,作为接收者角色(Receiver)*/
public class MusicPlayer {public void play() {System.out.println("播放");}public void stop() {System.out.println("暂停");}public void previousSong() {System.out.println("拖动进度条");}public void nextSong() {System.out.println("停止播放");}
}

创建命令角色(Command)

/*** 命令角色(Command)*/
public interface Command {void execute();
}

创建4个具体命令角色(Concrete Command),分别是实现播放,暂停,上一首,下一首的操作

/*** 播放操作*/
public class Play implements Command{private MusicPlayer musicPlayer;public Play(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.play();}
}
/*** 暂停操作*/
public class Stop implements Command{private MusicPlayer musicPlayer;public Stop(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.stop();}
}
/*** 切换上一首歌操作*/
public class PreviousSong implements Command{private MusicPlayer musicPlayer;public PreviousSong(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.previousSong();}
}
/*** 切换下一首歌操作*/
public class NextSong implements Command{private MusicPlayer musicPlayer;public NextSong(MusicPlayer musicPlayer) {this.musicPlayer = musicPlayer;}@Overridepublic void execute() {musicPlayer.nextSong();}
}

创建请求者角色(Invoker)

import java.util.ArrayList;
import java.util.List;/*** 请求者角色(Invoker)*/
public class Action {private List<Command> actions = new ArrayList<Command>();public void addAction(Command action){actions.add(action);}public void execute(Command action){action.execute();}public void executes(){for (Command action:actions) {action.execute();}actions.clear();}
}

创建客户端(Client)

/*** 客户端(Client)*/
public class Client {public static void main(String[] args) {MusicPlayer musicPlayer = new MusicPlayer();Action action = new Action();//立即执行操作action.execute(new Play(musicPlayer));action.execute(new Stop(musicPlayer));action.execute(new PreviousSong(musicPlayer));action.execute(new NextSong(musicPlayer));System.out.println("=========================");// 将方法添加到列表中,方便执行多条操作// 例如音乐播放器点下一首时,会切换下一首歌,并进行播放,这就设计一个按钮就行,然后这个按钮可以直接实现,切换下一首歌并播放的操作Action actionOther = new Action();actionOther.addAction(new NextSong(musicPlayer));actionOther.addAction(new Play(musicPlayer));actionOther.executes();}
}

输出结果如下所示:

播放
暂停
切换到上一首歌
切换到下一首歌
=========================
切换到下一首歌
播放

在上述例子中,
展示了命令模式在音乐播放器中的应用。MusicPlayer 类作为接收者,提供了播放、暂停、上一首和下一首的操作。Command 接口定义了命令的通用执行方法。四个具体命令类 (Play, Stop, PreviousSong, NextSong) 实现了这些操作,并持有 MusicPlayer 的引用。Action 类作为调用者,管理命令列表并执行命令。客户端通过 Action 对象立即执行单个命令或批量执行一系列命令,实现了命令的解耦和灵活管理。

总而言之:
命令模式是一种行为设计模式,用于将请求封装为对象,以便使用不同的请求对客户端进行参数化,支持命令队列、日志记录和撤销操作。核心概念包括命令接口(Command)、具体命令类(Concrete Command)、接收者(Receiver)和调用者(Invoker)。命令接口定义了所有命令共有的执行方法,具体命令类实现了命令接口并封装了接收者对象的引用,接收者执行实际的业务逻辑,调用者则请求命令对象执行命令。命令模式的优势在于降低调用者与接收者之间的耦合度,支持撤销操作和宏命令,易于扩展新命令。但同时也可能导致产生大量具体命令类,客户端需要管理命令对象,且可能存在性能开销。适用于GUI应用程序、事务处理、宏命令、命令行界面和需要撤销操作的场景。


以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git

相关文章:

设计模式详解(十九)——命令模式

命令模式简介 命令模式定义 命令模式&#xff08;Command Pattern&#xff09;是一种在面向对象程序设计中常用的行为型设计模式。命令模式的核心思想在于将请求封装成一个对象&#xff0c;从而使发出请求的责任和执行请求的责任分割开。它可以让请求发送者和请求接收者之间消…...

实战:MySQL数据同步神器之Canal

1.概叙 场景一&#xff1a;数据增量实时同步 项目中业务数据量比较大&#xff0c;每类业务表都达到千万级别&#xff0c;虽然做了分库分表&#xff0c;每张表数据控制在300W以下&#xff0c;但是效率还是达不到要求&#xff0c;为了提高查询效率&#xff0c;打算使用ES进行数…...

5.6软件工程-运维

运维 系统转换系统维护系统评价练习题 系统转换 新老系统的转换 系统转换是指&#xff1a;新系统开发完毕&#xff0c;投入运行&#xff0c;取代现有系统的过程&#xff0c;需要考虑多方面的问题&#xff0c;以实现与老系统的交接&#xff0c;有一下三种转换计划&#xff1a; …...

在JavaScript中如何确保构造函数只被new调用

构造函数是一个特殊的函数&#xff0c;用于初始化一个新创建的对象。它是在创建对象时自动调用的。构造函数通常用于为对象的属性赋值&#xff0c;或者执行其他必要的设置。 使用函数名大写字母开头&#xff0c;这是一种命名约定&#xff0c;用于区分构造函数和普通函数。如何…...

【数据结构算法经典题目刨析(c语言)】反转链表(图文详解)

&#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;数据结构经典题目刨析(c语言) 目录 一、题目描述 二、思路分析 三、代码实现 一、题目描述&#xff1a; 二、思路分析 &#xff1a; 通过三个指针n1,n2,n3来实现链表的反转 1.首先初始化 n1为…...

机器学习之争:Python vs R,谁更胜一筹?

一、引言 随着人工智能和大数据的迅速发展&#xff0c;机器学习已成为现代科技的重要组成部分。在医疗、金融、零售、制造等多个领域&#xff0c;机器学习技术的应用无处不在。从数据分析到预测建模&#xff0c;再到深度学习&#xff0c;机器学习正在改变我们的工作和生活方式…...

Vulnhub靶机:JANGOW_ 1.0.1

目录 前言&#xff1a; 一、安装虚拟机Jangow&#xff1a;1.0.1靶机 二、Web部分 前言&#xff1a; 难度&#xff1a;简单&#xff0c;本文使用VirtualBox打开&#xff0c;下载地址&#xff1a; https://download.vulnhub.com/jangow/jangow-01-1.0.1.ova 一、安装虚拟机J…...

Python脚本实现USB自动复制文件

USB驱动器作为常见的数据存储设备&#xff0c;经常用于数据传输和备份。 然而&#xff0c;我们在手动处理文件复制可能效率低下且容易出错。 因此&#xff0c;我们可以利用Python编写脚本来自动化这一过程&#xff0c;提高效率和数据安全性。 准备工作 首先&#xff0c;我们需…...

【C++学习第19天】最小生成树(对应无向图)

一、最小生成树 二、代码 1、Prim算法 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 510, INF 0x3f3f3f3f;int n, m; int g[N][N]; int dist[N]; bool st[N];int prim() {memset(dist, 0x3f, sizeof di…...

第一个 Flask 项目

第一个 Flask 项目 安装环境创建项目启动程序访问项目参数说明Flask对象的初始化参数app.run()参数 应用程序配置参数使用 Flask 的 config.from_object() 方法使用 Flask 的 config.from_pyfile() 方法使用 Flask 的 config.from_envvar() 方法步骤 1: 设置环境变量步骤 2: 编…...

利用 Angular 发挥环境的力量

一.介绍 您是否曾想过如何在不同的环境中为同一应用设置不同的颜色、标题或 API 调用&#xff1f;可以肯定的是&#xff0c;生产 API 和测试 API 是不同的&#xff0c;应谨慎使用。部署时&#xff0c;我们不会在项目的所有地方手动更改所有 API 调用。不应这样做&#xff0c;因…...

Vue3+TypeScript+printjs 实现标签批量打印功能

前言&#xff1a;临时性需求没怎么接触过前端&#xff0c;代码实现有问题及优化点希望大佬可以留言告知一下 开发工具&#xff1a;VS CODE 界面开发&#xff1a;Vue3TypeScriptElementPlus 打印组件&#xff1a;Print-JS 前端打印入口图&#xff1a; 标签页面&#xff1a; …...

微信文件如何直接打印及打印功能在哪里设置?

在数字化时代&#xff0c;打印需求依旧不可或缺&#xff0c;但传统打印店的高昂价格和不便操作常常让人头疼。幸运的是&#xff0c;琢贝打印作为一款集便捷、经济、高效于一体的网上打印平台&#xff0c;正逐渐成为众多用户的首选。特别是通过微信小程序下单&#xff0c;更是让…...

dataX -20240804-master分支

1、相关报错 Error: java.io.IOException: java.lang.RuntimeException: ORC split generation failed with exception: org.apache.orc.impl.SchemaEvolution$IllegalEvolutionException: ORC does not support type conversion from file type struct<nanos:int> (10)…...

【网络】传输层

传输层 一、预备知识1、端口号1、端口号范围划分2、知名端口号3、两个问题4、netstat && iostate5、pidof6、谈下面协议始终铭记两个问题 二、UDP协议&#xff08;简单&#xff09;1、UDP协议端格式2、UDP的特点3、面向数据报4、UDP缓冲区 三、TCP协议&#xff08;重点…...

学生管理系统之更新和删除、筛选

学生管理系统之更新和删除 建立新的窗口 添加组件 进行布局 使用Widget把二个放在一块,作为一列,然后全选进行栅格布局,最后添加弹簧进行微调。 编写增加的槽函数 在主函数中调用对话框...

教您一键批量下载拼多多批发图片信息,节省时间

图片是电商的核心展示手段&#xff0c;高质量、吸引人的图片能显著提升商品吸引力&#xff0c;增强用户体验&#xff0c;促进购买决策。良好的视觉呈现有助于品牌形象的塑造&#xff0c;提高转化率和客户满意度&#xff0c;对电商平台的流量和销售业绩具有直接影响。 使用图快…...

基于微信小程序的微课堂笔记的设计与实现(源码+论文+部署讲解等)

博主介绍&#xff1a;✌全网粉丝10W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术栈介绍&#xff1a;我是程序员阿龙&#xff…...

去噪扩散恢复模型

去噪扩散恢复模型 Bahjat Kawar 计算机科学系 以色列海法理工学院 bahjat.kawarcs.technion.ac.il Michael Elad 计算机科学系 以色列海法理工学院 eladcs.technion.ac.il Stefano Ermon 计算机科学系 美国加利福尼亚州斯坦福大学 ermoncs.stanford.edu …...

Stable Diffusion 官方模型V1.5版本下载

模型描述 Stable Diffusion的官方模型更适合绘制偏写实的风格&#xff0c;如果您想绘制二次元之类的风格&#xff0c;可以考虑下载本站的其它模型。 安装方法 将模型下载后&#xff0c;将会得到一个名为****.ckpt格式的文件&#xff0c;将该文件剪切至你的Stable Diffusion本…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...