Java二十三种设计模式-命令模式(18/23)

news2024/9/22 3:51:58

命令模式:将请求封装为对象的策略

概要

本文全面探讨了命令模式,从基础概念到实现细节,再到使用场景、优缺点分析,以及与其他设计模式的比较,并提供了最佳实践和替代方案,旨在帮助读者深入理解命令模式并在实际开发中有效应用。

 基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

第一部分:命令模式概述

1.1 定义与用途

命令模式(Command Pattern)是一种行为型设计模式,它将请求或操作封装成对象,允许用户使用不同的请求对客户进行参数化,并支持撤销操作。

命令模式是一种行为型设计模式,它将请求或操作封装为一个对象,这样你可以使用不同的请求、队列或日志请求来参数化其他对象,并支持撤销操作。

为何需要命令模式:

  • 解耦请求发送者与接收者:命令模式将请求发送者与接收者分离,提高系统的灵活性。
  • 支持撤销与重做:命令模式允许操作的撤销和重做,提高了用户体验。
  • 扩展性:允许系统在不修改现有代码的基础上扩展新命令。

1.2 命令模式的组成

命令(Command)

  • 定义:定义了执行操作的接口,包含执行命令的方法。
  • 职责:作为所有具体命令的抽象基类。

接收者(Receiver)

  • 定义:具体执行命令的对象,实现了命令接口中声明的操作。
  • 职责:接收命令请求并执行相应的操作。

调用者(Invoker)

  • 定义:要求命令对象执行请求。
  • 职责:维护命令对象的引用,并触发命令的执行。

客户端(Client)

  • 定义:创建具体的命令对象,并设置其接收者。
  • 职责:将调用者与命令对象关联,以便调用者可以执行命令。

角色之间的交互

  • 命令创建:客户端创建具体的命令对象,并将接收者传入命令对象。
  • 命令设置:调用者持有命令对象的引用,并在适当的时候调用命令的执行方法。
  • 命令执行:命令对象执行操作,接收者实际执行命令的细节。

命令模式通过将请求封装为对象,允许系统以统一的方式处理请求,同时支持撤销和重做操作。在下一部分中,我们将通过Java代码示例来展示命令模式的具体实现。

第二部分:命令模式的实现

2.1 Java实现示例

以下是使用Java语言实现命令模式的代码示例。假设我们有一个简单的文本编辑器,支持撤销和重做操作。

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

// 接收者:文本编辑器
class TextEditor {
    private String text;

    public TextEditor() {
        this.text = "";
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }
}

// 具体命令:添加文本
class AppendTextCommand implements Command {
    private TextEditor editor;
    private String appendText;

    public AppendTextCommand(TextEditor editor, String appendText) {
        this.editor = editor;
        this.appendText = appendText;
    }

    @Override
    public void execute() {
        editor.setText(editor.getText() + appendText);
    }

    @Override
    public void undo() {
        int index = editor.getText().lastIndexOf(appendText);
        if (index >= 0) {
            editor.setText(editor.getText().substring(0, index));
        }
    }
}

// 调用者:命令执行器
class CommandExecutor {
    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) {
        TextEditor editor = new TextEditor();
        CommandExecutor executor = new CommandExecutor();

        Command appendCmd = new AppendTextCommand(editor, "Hello World!");
        executor.setCommand(appendCmd);
        executor.executeCommand();

        System.out.println(editor.getText()); // 输出: Hello World!

        // 执行撤销操作
        appendCmd.undo();
        System.out.println(editor.getText()); // 输出: (空)
    }
}

2.2 命令模式中的角色和职责

命令(Command)

  • 职责:定义了执行操作的接口,允许将请求封装为一个对象。

接收者(Receiver)

  • 职责:具体执行命令中包含的操作,是命令要作用的对象。

调用者(Invoker)

  • 职责:要求命令对象执行请求,维护对命令对象的引用。

客户端(Client)

  • 职责:创建具体的命令对象,将接收者与命令关联,并提供给调用者。

相互作用

  • 命令创建:客户端创建具体的命令对象,指定命令的接收者和必要的参数。
  • 命令设置:调用者接收命令对象,并在适当的时候执行命令。
  • 命令执行:调用者调用命令对象的execute方法来执行操作,调用undo方法来撤销操作。

命令模式通过将请求封装为对象,允许系统以统一的方式处理请求,并支持撤销和重做操作。这种模式在需要对操作进行记录、撤销或重做的场景中非常有用。在下一部分中,我们将探讨命令模式的使用场景。

第三部分:命令模式的使用场景

3.1 需要将操作封装为对象的场景

在软件系统中,经常需要将操作封装为对象,以实现对操作的统一管理和调度。

讨论在需要将操作封装为对象时,命令模式的应用:

  • 操作的参数化:命令模式允许将操作的参数封装在命令对象中,使得操作可以在不同的时间点执行。
  • 操作的队列管理:通过命令对象,可以轻松地将操作加入队列、存储或序列化。
  • 接口的统一:命令模式提供了一个统一的操作执行接口,简化了调用者对操作的调用。

应用实例:

  • 任务调度系统:在任务调度系统中,命令模式可以将不同的任务封装为命令对象,统一调度和管理。
  • 图形界面操作:在图形用户界面中,用户的各种操作(如点击、拖拽)可以封装为命令对象,以支持撤销和重做功能。

3.2 需要支持撤销操作的场景

撤销操作是许多应用程序中的一个常见需求,特别是在文本编辑器、图形编辑器和其他需要用户交互的应用程序中。

分析在需要支持撤销操作时,命令模式的优势:

  • 撤销和重做支持:命令模式天然支持撤销操作,因为它将操作封装为对象,可以很容易地实现撤销和重做。
  • 操作的可逆性:通过命令对象的undo方法,可以轻松实现操作的逆向操作,满足用户撤销的需求。
  • 操作历史记录:命令模式可以与历史记录机制结合,存储操作序列,实现多级撤销和重做。

应用实例:

  • 文本编辑器:在文本编辑器中,用户的每次编辑操作都可以封装为一个命令对象,支持撤销和重做。
  • 游戏开发:在游戏开发中,玩家的操作可以封装为命令对象,以实现回放、撤销等功能。

命令模式通过将操作封装为对象,提供了一种灵活的方式来管理和调度操作,特别适用于需要撤销和重做功能的应用程序。在下一部分中,我们将讨论命令模式的优点与缺点。

第四部分:命令模式的优点与缺点

4.1 优点

解耦请求发送者与接收者

  • 灵活性增强:命令模式允许请求发送者和接收者之间没有直接联系,增加了系统的灵活性。

支持撤销操作

  • 操作可逆性:通过实现命令的undo()方法,命令模式支持撤销操作,提高了用户体验。

支持重做操作

  • 操作可重复性:在撤销操作之后,可以提供重做机制来恢复之前的状态。

支持事务性操作

  • 事务一致性:可以将一系列命令组合成一个事务,确保操作的一致性。

易于扩展

  • 开闭原则:遵循开闭原则,系统对扩展开放,对修改封闭,易于添加新命令。

增强安全性

  • 权限控制:可以对命令对象进行权限控制,限制对某些操作的访问。

4.2 缺点

增加系统复杂性

  • 类的数量:引入命令模式可能会增加系统中类的数量,每个命令都需要一个单独的类。

增加系统的开销

  • 性能问题:如果命令对象过多,可能会对性能产生影响。

难以管理命令依赖

  • 依赖关系:在复杂的系统中,命令之间的依赖关系可能难以管理。

难以实现跨系统命令

  • 系统边界:在分布式系统中,实现跨系统或跨网络的命令可能较为复杂。

可能引入循环依赖

  • 依赖循环:不当的使用可能导致命令对象之间的循环依赖。

撤销栈管理

  • 内存消耗:如果系统需要支持大量的撤销操作,撤销栈可能会消耗大量内存。

命令模式通过将请求封装为对象,提供了一种灵活的方式来管理和调度操作,支持撤销和重做功能。然而,它也需要谨慎使用,以避免增加系统的复杂性和维护难度。在实际应用中,根据具体需求和场景选择是否使用命令模式是非常重要的。在下一部分中,我们将比较命令模式与其他设计模式,并提供一些最佳实践和建议。

第五部分:命令模式与其他模式的比较

5.1 与策略模式的比较

策略模式

  • 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互换。
  • 特点:策略模式关注于算法的封装和替换,通常用于多种算法或行为的动态选择。

命令模式

  • 定义:命令模式将请求或操作封装为一个对象,允许用户使用不同的请求对客户进行参数化。
  • 特点:命令模式关注于请求的封装,支持撤销和重做操作,以及请求的排队和记录。

对比

  • 封装内容:策略模式封装的是算法或行为,命令模式封装的是请求或操作。
  • 使用场景:策略模式适用于需要根据不同条件选择不同算法的场景,命令模式适用于需要对请求进行参数化处理的场景。

5.2 与观察者模式的对比

观察者模式

  • 定义:观察者模式定义了对象之间的一对多依赖关系,当一个对象状态发生改变时,所有依赖于它的对象都会得到通知。
  • 特点:观察者模式关注于对象状态变化的广播机制,允许对象在状态变化时通知多个观察者。

命令模式

  • 定义:如前所述,命令模式关注于请求的封装和执行。

对比

  • 通信机制:观察者模式是一种对象间的通信机制,命令模式是一种请求的封装和执行机制。
  • 目的:观察者模式用于实现对象间的状态同步,命令模式用于将请求作为对象进行处理。

命令模式和策略模式、观察者模式都提供了处理对象间交互的不同方法。每种模式都有其独特的用途和优势,选择使用哪种模式取决于具体的设计需求和场景。在下一部分中,我们将提供命令模式的最佳实践和建议。

第六部分:命令模式的最佳实践和建议

6.1 最佳实践

确保命令的线程安全

  • 线程安全:确保命令对象在多线程环境中使用时是安全的,避免并发问题。

明确命令的撤销逻辑

  • 可逆操作:为每个命令实现清晰的撤销逻辑,确保undo()方法能够正确地撤销执行的操作。

使用宏命令简化复杂序列

  • 宏命令:当需要执行一系列命令时,使用宏命令来简化操作,作为一个整体进行撤销和重做。

定义清晰的命令执行和撤销接口

  • 接口规范:定义清晰的接口,如execute()undo(),确保所有命令遵循相同的规范。

考虑命令的持久化

  • 持久化存储:如果需要,实现命令的持久化机制,以便在系统重启后恢复命令状态。

保持命令的轻量级

  • 轻量设计:设计命令时应尽量保持轻量,避免命令对象过于复杂或庞大。

6.2 避免滥用

避免过度使用命令模式

  • 适用场景:只在确实需要将请求作为对象处理,或者需要撤销和重做功能时使用命令模式。

避免命令对象过于复杂

  • 简化设计:避免命令对象包含过多的逻辑,保持其职责单一。

避免滥用撤销和重做功能

  • 合理使用:不应过度依赖撤销和重做功能,这可能导致用户滥用,从而影响用户体验。

6.3 替代方案

使用函数式编程技术

  • 函数作为命令:在支持函数式编程的语言中,可以使用函数或函数式接口作为命令。

使用事件驱动模型

  • 事件作为命令:在事件驱动的系统中,可以使用事件来代替命令模式处理请求。

使用状态模式

  • 状态封装:当对象状态变化复杂时,可以使用状态模式来封装状态相关的操作。

使用策略模式

  • 算法封装:如果主要需求是根据不同条件选择不同的算法或行为,策略模式可能是更好的选择。

命令模式是一种强大的设计模式,用于将请求封装为对象,支持撤销和重做操作。合理使用命令模式并避免其缺点对于构建灵活、可维护的系统至关重要。了解其替代方案可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用命令模式,以达到最佳的设计效果。

结语

命令模式提供了一种强大的方法来封装操作,允许系统以不同的方式处理请求,并支持撤销操作。通过本文的深入分析,希望读者能够对命令模式有更全面的理解,并在实际开发中做出合理的设计选择。


博主还写了其他Java设计模式关联文章,请各位大佬批评指正:

(一)创建型模式(5种):

Java二十三种设计模式-单例模式(1/23)

Java二十三种设计模式-工厂方法模式(2/23)

Java二十三种设计模式-抽象工厂模式(3/23)

Java二十三种设计模式-建造者模式(4/23)

Java二十三种设计模式-原型模式(5/23)

(二)结构型模式(7种): 

Java二十三种设计模式-适配器模式(6/23)

Java二十三种设计模式-装饰器模式(7/23)

Java二十三种设计模式-代理模式(8/23)

Java二十三种设计模式-外观模式(9/23)

Java二十三种设计模式-桥接模式(10/23)

Java二十三种设计模式-组合模式(11/23)

Java二十三种设计模式-享元模式(12/23)

 (三)行为型模式(11种): 

Java二十三种设计模式-策略模式(13/23)

Java二十三种设计模式-模板方法模式(14/23)

Java二十三种设计模式-观察者模式(15/23)

Java二十三种设计模式-迭代子模式(16/23)

Java二十三种设计模式-责任链模式(17/23)

持续更新中......敬请关注

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

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

相关文章

【xr-frame】微信小程序xr-frame典型案例

微信小程序xr-frame典型案例 在之前的工作中,我大量使用XR-Frame框架进行AR开发,并积累了一些案例和业务代码。其中包括2D图像识别、手部动作识别、Gltf模型加载、动态模型加载、模型动画等内容。小程序部分使用TypeScript编写,而XR-Frame组…

利用puppeteer将html网页生成图片

1.什么是puppeteer? Puppeteer是一个Node库,它提供了一个高级API来通过DevTools协议控制Chromium或Chrome。 可以使用Puppeteer来自动化完成浏览器的操作,官方给出的一些使用场景如下: 生成页面PDF抓取 SPA(单页应用…

3.Windows Login Unlocker-忘记电脑密码也可以解决

想要解锁Windows系统的开机密码,但官网的传统方法只适合Windows本地账户,对微软账户或PIN码()束手无策?别担心,小编之前推荐过的「Windows Login Unlocker」软件能为您排忧解难。这款出色的工具不仅能够轻松绕过各种Windows密码&a…

C语言-写一个用矩形法求定积分的通用函数,分别求积分区间为[0,1]sinx,cosx,e的x方的定积分

一、题目要求: 二、思路 ①数学方面:矩形法求定积分的公式 将积分图形划分成为指定数量的矩形,求取各个矩形的面积,然后最终进行累加得到结果 1.积分区间: [num1, num2] 2.分割数量:count 每个矩形的边长:dx(num2-num1)/count 3.被积分…

智慧草莓基地管理系统--论文pf

TOC springboot359智慧草莓基地管理系统--论文pf 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大,随着当前时代的信息化,科学化发展,让社会各行业领域都争相使用新的信息技术,对行业内的各种相关数据进行科学化&#xf…

泰安鲁菜根普照店重装开业:传承与创新并举 品味舌尖上的泰安

8月17日,泰安鲁菜根普照店重装开业。店内装修以泰山文化为主题,营造出一种浓郁的地方文化特色氛围。这家以泰山文化为底蕴,以大汶河传统民俗食材为基础的餐饮企业,一直致力于发掘和传承泰山周边及汶河两岸的传统特色美食&#xff…

【漫谈C语言和嵌入式009】探索LVDT:线性可变差动变压器的工作原理与应用

引言 在现代工业和工程领域中,精确的位移测量是许多系统正常运行的关键。线性可变差动变压器(LVDT, Linear Variable Differential Transformer)是一种广泛使用的位移传感器,因其高精度、可靠性和耐用性在各种应用中得到了普遍认可…

iOS(OC)学习第1天-怎么设置UI

xCode 版本为 新建工程 xCode->iOS->App->输入工程名称 项目结构 storyboard文件:可以通过拖动方式添加UI的UI布局文件,理解为Android的XML布局文件 名字说明Main.storyboard首页LaunchScreen.storyboard引导页 添加布局 引导页 设置组件的属…

复现DOM破坏案例

准备工作&#xff1a; 做好代理然后访问靶场 XSS Game - Learning XSS Made Simple! | Created by PwnFunction 第一关 Ma Spaghet! 这是源代码部分&#xff1a; <!-- Challenge --> <h2 id"spaghet"></h2> <script> spaghet.innerHTM…

【推荐100个unity插件之25】使用Vroid进行二次元建模,并在unity中使用VRM模型——URP-UniVrm插件的使用

最终效果 文章目录 最终效果什么是Vriod官网地址下载安装使用导出模型unity使用VRM模型导入URP-UniVrm插件 Blender使用Blender安装Cats Blender Plugin 插件Blender安装VRM-Addon-for-Blender插件导入VRM模型导出为FBX模型 使用别人的VRM模型完结 什么是Vriod 如果你玩过能捏…

经典动作手机游戏:《艾希》安卓手机游戏下载

《艾希手游》是一款以女性为主角的游戏&#xff0c;玩家在游戏中将扮演主角艾希&#xff0c;在各种场景中进行冒险&#xff0c;探索剧情和解开谜题。这款游戏的画面精美&#xff0c;操作简单易上手&#xff0c;同时提供了丰富的剧情和多样的玩法。 下载地址&#xff1a;https:/…

氙灯老化试验箱试验机

氙灯老化试验箱&#xff0c;采用6.5KW大功率的精密水冷式氙灯&#xff0c;曝晒面积达到了6500cm2 功能强大&#xff0c;测试结果可靠 ◆ 满足国内外所有氙灯测试标准要求。 ◆ 采用氙灯灯管及滤光器组件&#xff0c;保证试验数据的可比性和重现性。 ◆ 自动旋转式三层鼓型样板架…

MATLAB根据数值画直方图

一直很纠结MATLAB为什么不提供根据数值&#xff08;或统计值&#xff09;画直方图的函数&#xff0c;只给一个不专业的bar&#xff0c;原来histogram支持。 edges [0-0.5:70.5]; counts [508 821 898 892 552 181 159 85];figure; histogram(BinEdges,edges,BinCounts,count…

SAP Memory ABAP Memory超级详细解析

SAP Memory & ABAP Memory超级详细解析_abap set parameter id-CSDN博客 FREE MEMORY ID ZTESTMAT. 清空指定的ABAPmemory FREE MEMORY. 清空externalsession内的所有ABAPmemory 最后请注意 IMPORT…

【Spring Boot-SpringBoot怎么实现自动配置】

目录 什么是Spring Boot自动配置 自动配置中需要的重要注解 一.Condition 二.Enable 三.EnableAutoConfiguration 实现一个自定义starter 什么是Spring Boot自动配置 SpringBoot的自动配置简单来说就是当spring容器启动后&#xff0c;一些配置类、bean对象就自动存入到了…

Python新手入门指南:从零开始学编程

欢迎来到Python的世界&#xff01;Python是一种功能强大、易于学习且用途广泛的编程语言。无论你是完全没有编程经验的新手&#xff0c;还是想要学习新技能的开发者&#xff0c;Python都是一个非常好的起点。接下来&#xff0c;我们将一起踏上这段编程之旅&#xff0c;从基础语…

机器学习第十一章-特征选择与稀疏学习

11.1子集收集与评价 属性称为"特征" &#xff0c;对当前学习任务有用的属性称为"相关特征" 、没什么用的属性称为"无关特 征" . 从给定的特征集合中选择出相关特征于集的过程&#xff0c;称为"特征选择"。 特征选择是一个重要的"…

Linux系统中的弹性计算功能

在当今数字化时代&#xff0c;弹性计算已经成为信息技术领域的重要概念之一。弹性计算指的是根据需要自动调整计算资源&#xff0c;以满足应用程序的需求。这种灵活性和自适应性使得弹性计算成为了云计算、大数据、人工智能等领域的核心技术之一。在这个领域中&#xff0c;Linu…

嵌入式软件--数电基础 DAY 4

1.SR锁存器 1》四种状态&#xff1a; S R Q Q set状态&#xff1a; 0 1 1 0 Reset状态&#xff1a; 1 0 0 1 维持状态&#xff1a; 1 1 维持上个状态 无意义状态…

VUE中出现Cannot find module ‘@/api/xxx.js‘ or its corresponding type declarations

在使用VSCode编写Vue程序时发现之前使用以下代码时却报出了错误 import {getEmployeeList} from /api/employee\ 保证文件地址正确且其中的方法也可以正常调用&#xff0c;只是报出了错误&#xff0c;该行代码上加入一个‘//ts-ignore’就可以解决。 修改后的代码 //ts-ig…