命令模式的理解和实践

        在软件开发中,设计模式是开发者们经过长期实践总结出来的、可复用的解决方案,用于解决常见的设计问题。命令模式(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;
    }

    @Override
    public void execute() {
        receiver.openFile();
    }
}

// 保存文件命令
public class SaveFileCommand implements Command {
    private Receiver receiver;

    public SaveFileCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.saveFile();
    }
}

// 退出命令
public class ExitCommand implements Command {
    private Receiver receiver;

    public ExitCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public 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.


总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】关系操作符的全面解析与高级应用

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯关系操作符1.关系操作符的分类与语义2.关系操作符的连用问题3.浮点数比较的精度问题问题示例解决方案 💯总结核心要点 💯小结 💯前言 在…

python爬虫--某房源网站验证码破解

文章目录 使用模块爬取目标验证码技术细节实现成果代码实现使用模块 requests请求模块 lxml数据解析模块 ddddocr光学识别 爬取目标 网站验证码破解思路是统一的,本文以城市列表为例 目标获取城市名以及城市连接,之后获取城市房源信息技术直接替换地址即可 验证码 技术…

java+ssm+mysql校园物品租赁网

项目介绍: 使用javassmmysql开发的校园物品租赁网,系统包含管理员、用户角色,功能如下: 管理员:用户管理;物品管理(物品种类、物品信息、评论信息);订单管理&#xff1…

【JS】简单CSS简单JS写的上传进度条

纯JS写的&#xff0c;简单的上传进度条&#xff0c;当上传的文件较大&#xff0c;加一个动态画面&#xff0c;就不会让人觉得出错了或网络卡了 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"v…

Oracle系统性能监控工具oswatcher演示

1、关于 OSW OSWatcher 的使用符合 Oracle 的标准许可条款&#xff0c;并且不需要额外的许可即可使用&#xff01;&#xff01;&#xff01;&#xff01; OSWatcher (oswbb) 是一种 UNIX shell 脚本的集合&#xff0c;主要用于收集和归档操作系统和网络的度量&#xff0c;以便…

Oracle EBS PAC 如何复修非标任务单生产生非常大的PAC成本?

系统环境 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题症状 非标准任务单组件和装配相同物料A,俗称投入A产A。该物料A的期初数量为0。 上期成本假设为20,而本期成本爆增至563.674234。关键问题点: 由于该物料没有期初数量,无法通过“更新定期成本”指定“新期本…

word实践:正文/标题/表图等的共用模板样式设置

说在前面 最近使用word新建文件很多&#xff0c;发现要给大毛病&#xff0c;每次新建一个word文件&#xff0c;标题/正文的字体、大小和间距都要重新设置一遍&#xff0c;而且每次设置这些样式都忘记了参数&#xff0c;今天记录一下&#xff0c;以便后续方便查看使用。现在就以…

java抽奖系统(一)2.0

1. 项⽬介绍 1.1 背景 随着数字营销的兴起&#xff0c;企业越来越重视通过在线活动来吸引和留住客⼾。抽奖活动作为⼀种有效的营 销⼿段&#xff0c;能够显著提升⽤⼾参与度和品牌曝光率。于是我们就开发了以抽奖活动作为背景的Spring Boot项⽬&#xff0c;通过这个项⽬提供⼀…

spring 源码分析

1 IOC 源码解析 BeanDefinition: bean的定义。里面会有beanClass、beanName、scope等属性 beanClass&#xff1a;通过Class.forName生成的Class 对象beanName&#xff1a;context.getBean(“account”)&#xff0c;acount就是beanNamescope: 作用区分单例bean、原型bean Bea…

Android水波纹效果

Android水波纹效果 需要到水波纹效果的场景还蛮少的。万一刚好你需要呢 一、思路&#xff1a; 自定义组件SpreadView 二、效果图&#xff1a; 看视频更直观点&#xff1a; Android轮子分享-水波纹效果 三、关键代码&#xff1a; public class SpreadView extends View {pr…

用 NotePad++ 运行 Java 程序

安装包 网盘链接 下载得到的安装包: 安装步骤 双击安装包开始安装. 安装完成: 配置编码 用 NotePad 写 Java 程序时, 需要设置编码. 在 设置, 首选项, 新建 中进行设置, 可以对每一个新建的文件起作用. 之前写的文件不起作用. 在文件名处右键, 可以快速打开 CMD 窗口, 且路…

TaskBuilder SQL执行工具

为了方便开发者连接当前任擎服务器上配置的各个数据源对应的数据库进行相关操作&#xff0c;TaskBuilder提供了一个SQL执行工具&#xff0c;点击系统侧边栏里的执行SQL图标 &#xff0c;即可打开该工具&#xff0c;界面如下图所示&#xff1a; 该工具从上至下分为三个区域&a…

学生信息管理系统(简化版)数据库部分

使用Mysql&#xff0c;与navicat工具 下面是mysql创建的代码&#xff0c;可做必要修改 -- 创建学生学籍信息表 CREATE TABLE StudentEnrollment (-- 学号&#xff0c;作为主键student_id VARCHAR(8) NOT NULL,-- 学生姓名stu_name VARCHAR(8) NOT NULL,-- 学生性别gender VARC…

计算机网络之传输层协议TCP

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 计算机网络之传输层协议TCP 收录于专栏【计算机网络】 本专栏旨在分享学习计算机网络的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目…

美畅物联丨观看实时视频对服务器带宽有什么要求?

​随着互联网的迅猛发展&#xff0c;实时视频观看已然成为人们日常生活中不可或缺的一部分。不管是视频会议、在线教育&#xff0c;还是在线娱乐&#xff0c;实时视频都起到了极为重要的作用。不过&#xff0c;实时视频的流畅播放对服务器的带宽有着极高的要求。本文将深入探究…

SWIRL:有望成为2025年顶级AI搜索引擎

现在几乎每家公司都会有内部文档系统&#xff0c;如阿里的语雀、钉钉&#xff0c;字节的飞书&#xff0c;Confluence&#xff0c;印象笔记等等都可以提供给B端在局域网部署。因此&#xff0c;如果能把搜索功能做得高效&#xff0c;就能提高自家产品的竞争力。 想象一下&#xf…

技术栈6:Docker入门 Linux入门指令

目录 1.Linux系统目录结构 2.处理目录的常用命令 3.Docker概述 4.Docker历史 5.Docker基本组成 6.Docker底层原理 7.Docker修改镜像源 8.Docker基本命令 9.Docker创建Nginx实战 10.数据卷 11.本地目录直接挂载* 12.镜像和dockerfile 13.容器互联与自定义网络 14.…

LeetCode - #156 上下翻转二叉树(会员题)

文章目录 前言1. 描述2. 示例3. 答案关于我们 前言 本题为 LeetCode 的高级会员解锁题 我们社区陆续会将顾毅&#xff08;Netflix 增长黑客&#xff0c;《iOS 面试之道》作者&#xff0c;ACE 职业健身教练。&#xff09;的 Swift 算法题题解整理为文字版以方便大家学习与阅读…

汽车零部件设计之——麦弗逊悬架KC特性分析仿真APP介绍

汽车零部件是汽车工业的基石&#xff0c;是构成车辆的基础元素。一辆汽车通常由上万件零部件组成&#xff0c;包括发动机系统、传动系统、制动系统、电子控制系统等&#xff0c;它们共同确保了汽车的安全、可靠性及高效运行。在汽车产业快速发展的今天&#xff0c;汽车零部件需…

STM32串口接收与发送(关于为什么接收不需要中断而发生需要以及HAL_UART_Transmit和HAL_UART_Transmit_IT的区别)

一、HAL_UART_Transmit和HAL_UART_Transmit_IT的区别 1. HAL_UART_Transmit_IT&#xff08;非阻塞模式&#xff09;&#xff1a; HAL_UART_Transmit_IT 是非阻塞的传输函数&#xff0c;也就是说&#xff0c;当你调用 HAL_UART_Transmit_IT 时&#xff0c;它不会等到数据完全发…