当前位置: 首页 > 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要减一…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...