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

设计模式十五:命令模式(Command Pattern)

命令模式(Command Pattern)是一种行为型设计模式,它旨在将请求或操作封装成一个对象,从而允许你将不同的请求参数化,并且能够在不同的时间点执行或者队列化这些请求。这种模式使得请求发送者与接收者之间解耦,同时也支持撤销操作和日志记录。

使用场景

命令模式适用于需要将操作封装成对象,并支持命令的队列化、撤销、重做、日志记录等功能的场景。它有助于降低系统的耦合度,使得系统更加灵活、可扩展和易于维护。
例如说:
当需要将请求发送者和接收者解耦时。
当需要支持撤销、重做、日志记录等功能时。
当需要将一系列操作队列化、延迟执行或按顺序执行时。
命令模式在以下情况下特别有用:

  1. 撤销和重做功能:
    当需要实现撤销和重做操作时,命令模式是一个很好的选择。通过将每个操作封装成命令对象,并将命令对象的历史记录保存下来,可以轻松地支持撤销和重做功能。
  2. 菜单和工具栏:
    在图形用户界面(GUI)应用程序中,命令模式常用于实现菜单项、工具栏按钮等的操作。每个菜单项或按钮可以关联一个命令对象,从而使得用户的操作可以以命令的方式进行管理和执行。
  3. 异步任务调度:
    命令模式可以用于将异步任务封装成命令对象,然后将这些命令对象加入到任务队列中进行调度和执行。
  4. 日志记录和审计:
    通过使用命令模式,可以很容易地记录每个命令的执行历史,用于日志记录和审计目的。
  5. 数据库事务:
    在数据库操作中,命令模式可以用于封装各种数据库操作(如插入、更新、删除),从而支持事务管理。
  6. 智能家居和自动化系统:
    在智能家居和自动化系统中,命令模式可以用于控制各种设备(灯光、电器、窗帘等)的开关操作。
  7. 游戏中的操作和指令:
    在游戏开发中,命令模式可以用于实现玩家的操作和指令,例如玩家的移动、攻击、释放技能等。
  8. 模拟和仿真系统:
    在模拟和仿真领域,命令模式可以用于描述和执行模拟的各种操作和指令。

涉及的几个角色

  1. 命令(Command):
    定义了一个命令的接口,通常包括一个 execute() 方法,用于执行该命令。
  2. 具体命令(Concrete Command):
    实现了命令接口,将一个具体的操作与一个接收者关联起来,负责调用接收者执行操作。
  3. 接收者(Receiver):
    执行实际操作的对象,命令对象将请求委派给接收者来执行具体操作。
  4. 调用者/请求者(Invoker):
    负责创建命令对象,并在需要的时候调用命令的 execute() 方法。
  5. 客户端(Client):
    创建具体命令和接收者,并将它们组装起来,构建命令的发送者和接收者之间的关系

java代码实例

以下实例演示了如何使用命令模式实现撤销操作
命令接口

public interface Command_ {//执行写操作void execute();//执行撤销操作void undo();
}

具体命令实现类

public class EditCommand implements Command_ {private TextEditor editor;private String newText;private String prevText;public EditCommand(TextEditor editor, String newText) {this.editor = editor;this.newText = newText;}public void execute() {prevText = editor.getText();editor.setText(newText);}public void undo() {editor.setText(prevText);}
}

接收者

public class TextEditor {private String text = "";public String getText() {return text;}public void setText(String newText) {text = newText;}
}

调用者/请求者

public class TextCommandInvoker {//这段代码创建了一个私有的堆栈数据结构commandHistory,//用于存储实现了 Command_ 接口的对象,实现命令模式等场景中会很有用//用来记录和管理执行过的命令对象,以便支持撤销、重做等操作。private Stack<Command_> commandHistory = new Stack<>();public void executeCommand(Command_ command) {command.execute();commandHistory.push(command);}public void undo() {if (!commandHistory.isEmpty()) {Command_ lastCommand = commandHistory.pop();lastCommand.undo();}}}

客户端

public static void main(String[] args) {TextEditor editor = new TextEditor();TextCommandInvoker invoker = new TextCommandInvoker();Command_ editCommand1 = new EditCommand(editor, "Hello");Command_ editCommand2 = new EditCommand(editor, "Hello, World");invoker.executeCommand(editCommand1);System.out.println("Editor Text: " + editor.getText());invoker.executeCommand(editCommand2);System.out.println("Editor Text: " + editor.getText());invoker.undo();System.out.println("Editor Text after Undo: " + editor.getText());invoker.undo();System.out.println("Editor Text after Undo: " + editor.getText());
}

输出结果

Editor Text: Hello
Editor Text: Hello, World
Editor Text after Undo: Hello
Editor Text after Undo: 

命令模式的优缺点

命令模式在需要实现命令的撤销、重做、队列化等功能时非常有用。它可以提高代码的灵活性和可维护性,但在应用时需要权衡好优缺点,并根据具体情况进行选择。
优点:

  1. 松耦合:
    命令模式将请求者和接收者解耦,请求者不需要知道接收者的细节,只需通过命令对象来间接调用。这降低了系统的耦合性,使得系统的各个部分可以独立地变化。
  2. 可扩展性:
    可以很容易地添加新的命令类和接收者类,而不需要修改现有的代码。这使得系统更加灵活和可扩展。
  3. 支持撤销和重做:
    命令模式可以记录请求的历史,从而支持撤销和重做操作。通过保存命令对象的历史记录,可以在需要时逆转操作。
  4. 日志记录:
    命令模式可以用于记录请求和操作的日志,从而实现日志记录和审计功能。
  5. 适用于队列和任务调度:
    命令模式可以将请求放入队列中,支持任务的异步执行和调度。

缺点:

  1. 类膨胀:
    实现命令模式可能需要创建大量的命令类,尤其在具有多个操作和接收者的情况下,会导致类的膨胀。
  2. 增加复杂性:
    在一些情况下,命令模式可能增加了代码的复杂性,特别是在存在多个命令类、接收者类和请求者类之间的关系时。
  3. 不适合复杂场景:
    在某些复杂场景下,命令模式可能不太适合,因为可能会涉及大量的命令类和对象之间的关系,导致设计变得复杂。
  4. 性能考虑:
    命令模式可能会引入一定的性能开销,因为需要将请求封装成对象,并将其在不同的对象之间传递。

相关文章:

设计模式十五:命令模式(Command Pattern)

命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;它旨在将请求或操作封装成一个对象&#xff0c;从而允许你将不同的请求参数化&#xff0c;并且能够在不同的时间点执行或者队列化这些请求。这种模式使得请求发送者与接收者之间解耦&#xff…...

FPGA GTP全网最细讲解,aurora 8b/10b协议,HDMI视频传输,提供4套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTP 全网最细解读GTP 基本结构GTP 发送和接收处理流程GTP 的参考时钟GTP 发送接口GTP 接收接口GTP IP核调用和使用 4、设计思路框架HDMI输入视频配置及采集视频数据组包GTP aurora 8b/10b数据对齐视频数据解包图像…...

用dcker极简打包java.jar镜像并启动

用dcker极简打包java.jar镜像并启动 一、本地打包好jar包 二、新建文件夹&#xff0c;将步骤1中的jar包拷贝到文件夹下 三、同目录下新建Dockerfile ## 基础镜像&#xff0c;这里用的是openjdk:8 FROM openjdk:8## 将步骤一打包好的jar包 拷贝到镜像的 跟目录下[目录可以自定义…...

设计模式——创建型

1.单例模式 单例模式主要用于某个类有且只能用一个对象的场景&#xff0c;单例模式下不能外部实例化对象&#xff0c;由类内部自行私有化实例对象并提供一个可以获得该对象的方法。单例模式主要有饿汉模式&#xff08;安全&#xff0c;但在编译时就会自动创建对象&#xff0c;…...

iTOP-i.MX8M开发板添加USB网络设备驱动

选中支持 USB 网络设备驱动&#xff0c;如下图所示&#xff1a; [*] Device Drivers→ *- Network device support → USB Network Adapters→ {*} Multi-purpose USB Networking Framework 将光标移动到 save 保存&#xff0c;如下图所示&#xff1a; 保存到 arch/arm64/c…...

分类预测 | MATLAB实现GAPSO-LSSVM多输入分类预测

分类预测 | MATLAB实现GAPSO-LSSVM多输入分类预测 目录 分类预测 | MATLAB实现GAPSO-LSSVM多输入分类预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.分类预测 | MATLAB实现GAPSO-LSSVM多输入分类预测 2.代码说明&#xff1a;要求于Matlab 2021版及以上版本。 程序…...

JMeter 的并发设置教程

JMeter 是一个功能强大的性能测试工具&#xff0c;可以模拟许多用户同时访问应用程序的情况。在使用 JMeter 进行性能测试时&#xff0c;设置并发是非常重要的。本文将介绍如何在 JMeter 中设置并发和查看报告。 设置并发 并发是在线程组下的线程属性中设置的。 线程数&#…...

数据治理有哪些产品

数据治理是现代企业管理中至关重要的一个环节。随着企业的数据量不断增长&#xff0c;如何有效地管理和利用数据成为了一个亟待解决的问题。幸运的是&#xff0c;市场上已经涌现出了许多优秀的数据治理产品&#xff0c;下面就来介绍一些常见的数据治理产品。 首先&#xff0c;我…...

windows安装go,以及配置工作区,配置vscode开发环境

下载安装go 我安装在D:\go路径下配置环境变量 添加GOROOT value为D:\go修改path 添加%GOROOT%\bin添加GOPATH value为%USERPROFILE%\go 其中GOPATH 是我们自己开发的工作区&#xff0c;其中包含三个folder bin,pkg,以及src&#xff0c;其中src为我们编写代码的位置 配置vscod…...

第五章nginx负载均衡

负载均衡&#xff1a;反向代理来实现 nginx的七层代理&#xff1a; 七层是最常用的反向代理方式&#xff0c;只能配置在nginx配置文件的hppt模块中。而且配置方法名称&#xff1a;upstream模块&#xff0c;不能写在server中&#xff0c;也不能在location中&#xff0c;在http…...

MATLAB计算一组坐标点的相互距离(pdist、squareform、pdist2函数)

如果有一组坐标P(X,Y)&#xff0c;包含多个点的X和Y坐标&#xff0c;计算其坐标点之间的相互距离 一、坐标点 P[1 1;5 2;3 6;8 8;4 5;5 1; 6 9];二、pdist函数 输出的结果是一维数组&#xff0c;获得任意两个坐标之间的距离&#xff0c;但没有对应关系 Dpdist(P)三、square…...

我国农机自动驾驶系统需求日益增长,北斗系统赋能精准农业

中国现代农业的发展&#xff0c;离不开智能化、自动化设备&#xff0c;迫切需要自动驾驶系统与农用机械的密切结合。自动驾驶农机不仅能够缓解劳动力短缺问题&#xff0c;提升劳作生产效率&#xff0c;同时还能对农业进行智慧化升级&#xff0c;成为解决当下农业痛点的有效手段…...

防雷检测行业应用完整解决方案

防雷检测是指对雷电防护装置的性能、质量和安全进行检测的活动&#xff0c;是保障人民生命财产和公共安全的重要措施。防雷检测的作用和意义主要有以下几点&#xff1a; 防止或减少雷电灾害事故的发生。雷电是一种自然现象&#xff0c;具有不可预测、不可控制和高能量等特点&a…...

16.4 【Linux】特殊文件与程序

16.4.1 具有 SUID/SGID 权限的指令执行状态 SUID 的权限其实与程序的相关性非常的大&#xff01;为什么呢&#xff1f;先来看看 SUID 的程序是如何被一般使用者执行&#xff0c;且具有什么特色呢&#xff1f; SUID 权限仅对二进制程序&#xff08;binary program&#xff09;…...

qrcode.react生成二维码

qrcode.react 是一个**用于生成二维码&#xff08;QR 码&#xff09;的 React 组件库。**它提供了一个 React 组件&#xff0c;可以轻松地在 React 应用程序中生成和显示 QR 码。 使用 qrcode.react&#xff0c;可以以声明式的方式在 React 组件中定义 QR 码的内容、尺寸、颜色…...

ETF套利及交易者如何进行套利的

ETF套利 什么是ETF套利为什么同一ETF在不同交易所上的价格会出现差异&#xff1f;如何操作ETF套利交易所如何解决ETF套利问题的&#xff1f; 什么是ETF套利 ETF&#xff08;Exchange-Traded Fund&#xff09;套利是一种通过利用市场中不同交易所交易价格之间的差异来获得利润的…...

了解异或的好处和用途

1.什么是异或&#xff1f; 异或&#xff1a;对于二进制&#xff0c;相同为0 不同为11 ⊕ 1 00 ⊕ 0 01 ⊕ 0 10 ⊕ 1 1 2.异或的好处&#xff1f; 异或的好处&#xff1f;1.快速比较两个值 2.xor a a例如 a 3 011xor 0110003.可以使用 异或 来使某些特定的位翻转【原因…...

vue函数式组件

<template>改为<template functional> 即可然后模板里使用到父组件参数的话&#xff0c;需在变量前面加上 props&#xff0c;如 <div>{{count}}</div> 改为 <div>{{props.count}}</div>如果组件比较简单&#xff0c;只是展示数据的话&…...

Idea Live Template 功能总结

文章目录 Java自带的template属性模板psf——public static finalpsfi——public static final intpsfi——public static final StringSt——String 方法模板psvm——main方法sout——打印语句iter——for迭代循环fori——for循环 代码块模板if-e —— if elseelse-if 自定义自…...

场景入门12----构造脚本搭建栅栏和石头墙

打开任意一个蓝图都有构造脚本&#xff0c;就是当这个蓝图在诞生时就会运行的东西 新建一个蓝图&#xff0c;在构造函数里添加静态网格体&#xff0c;把蓝图拖出来就能显示 多个栅栏 创建多个栅栏。新建一个变量为栅栏数量&#xff0c;数组从0开始&#xff0c;所以countt要减一…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...