设计模式第19讲——命令模式(Command)-程序员宅基地

技术标签: 面试  java  命令模式  设计模式  

一、什么是命令模式

命令模式(Command Pattern)是一种行为型设计模式,又叫动作模式或事务模式。它将请求(命令)封装成对象,使得可以用不同的请求对客户端进行参数化,具体的请求可以在运行时更改、排队或记录,它讲发出者和接收者解耦(顺序:发出者-->命令-->接收者
本质:封装请求

二、角色组成

抽象命令(Command):命令是一个抽象接口,定义了执行操作的统一方法。具体的命令类会实现这个接口,并提供执行相应操作的具体逻辑。
具体命令(Concrete Command):具体命令类实现了抽象命令,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
接收者(Receiver):执行实际命令的类,命令对象会调用接收者的方法来执行请求。
调用者(Invoker):持有命令对象,通常是多个,并通过访问命令对象来执行相关请求,他不直接访问接收者。

三、优缺点

 优点:

  • 解耦:命令模式可以将发送命令的对象和执行命令的对象解耦,使得两者可以独立变化。
  • 可扩展性:可以方便地添加新的命令类和接收者类,而无需修改现有的代码结构。
  • 容易实现撤销和重做功能:由于每个命令对象都封装了具体的操作,可以很容易地实现命令的撤销和重做功能。
  • 支持操作的队列化和延迟执行:命令对象可以被组织成队列或堆栈,实现对操作的排队和延迟执行。

缺点:

  • 增加了类和对象的数量:使用命令模式可能会增加一些新的类和对象,从而增加了代码的复杂性。
  • 需要额外的开销:封装命令对象和操作会增加一些额外的开销,可能会稍微降低性能。
  • 可能导致过多的具体命令类:如果系统的命令比较多,可能会导致需要创建很多具体的命令类,增加了代码维护的难度。

四、应用场景

4.1 生活场景

  •  餐厅点餐:在一家餐厅中,服务员充当调用者,厨师充当接收者,菜品可以作为具体命令。当顾客想点菜时,服务员会将顾客的需求封装成一个命令对象,并传递给厨师。厨师根据命令对象中的信息来完成相应的烹饪工作。这样,顾客和厨师之间不需要直接沟通,而是通过命令对象来实现点餐和烹饪的解耦。
  • 遥控器控制家电:拿电视遥控器举例,遥控器是调用者,电视是接收者。每个按键都可以看作是一个具体命令,例如音量加、音量减、切换频道等。当用户按下某个按键时,遥控器会发送相应的命令给电视,然后电视根据命令执行相应的操作,如增加音量、减小音量或切换频道。

4.2 java场景

  • Runnable接口:Java中的Runnable接口就是一个典型的命令模式的应用。Runnable接口封装了需要执行的任务,然后可以交给线程去执行。
  • Timer和TimerTask类:这两个类用于定时任务调度,TimerTask类封装了要执行的任务,然后由Timer类作为调用者执行这些任务。
  • Statement接口:在Java中与数据库交互时,SQL语句被封装成Statement对象,然后由数据库驱动程序执行相应的命令。

五、代码实现

下面以餐厅点餐为例,解释以下命令模式。在一家餐厅中,服务员充当调用者,厨师充当接收者,菜品可以作为具体命令。当顾客想点菜时,服务员会将顾客的需求封装成一个命令对象,并传递给厨师。厨师根据命令对象中的信息来完成相应的烹饪工作。

抽象命令:Command
具体命令:OrderCommand
接收者:Chef
调用者:Waiter

5.0 UML类图

5.1 抽象命令(Command)——Command

首先,创建一个命令接口(Command),它定义了点菜和取消点菜的方法

/**
 * @author Created by njy on 2023/6/29
 * 1.抽象命令(Command): 点菜和取消两个命令
 * 定义:命令是一个抽象接口,定义了执行操作的统一方法。
 */
public interface Command {
    //点菜
    void order();
    //取消点菜
    void cancelOrder();
}

5.2 接收者(Receiver)——Chef

创建接收者类(Chef)实现具体的烹饪操作。

/**
 * @author Created by njy on 2023/6/29
 * 2.接收者(Receiver):厨师
 * 定义:执行实际命令的类,命令对象会调用接收者的方法来执行请求。
 */
public class Chef {

    public void cook() {
        System.out.println("厨师执行点菜命令:正在烹饪菜品...");
    }

    public void cancelCooking() {
        System.out.println("厨师执行取消命令:停止烹饪菜品!");
    }
}

5.3 具体命令(Concrete Command)——OrderCommand

创建具体命令类(如点菜命令)实现命令接口,并将点菜的请求和具体的烹饪者(厨师)关联起来

/**
 * @author Created by njy on 2023/6/29
 * 3.具体命令(Concrete Command):点菜命令
 * 定义:具体命令类实现了抽象命令,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
 */
public class OrderCommand implements Command{
    // 厨师
    private Chef chef;

    public OrderCommand(Chef chef) {
        this.chef = chef;
    }

    public void order() {
        //与具体的烹饪者(厨师)关联,执行点菜操作
        chef.cook();
    }

    public void cancelOrder() {
        //与具体的烹饪者(厨师)关联,执行取消点菜操作
        chef.cancelCooking();
    }
}

5.4 调用者(Invoker)——Waiter

最后,在服务员类中,创建调用者(服务员),接收命令(点菜命令),并执行相应的操作

/**
 * @author Created by njy on 2023/6/29
 * 4.调用者(Invoker):服务员
 * 定义:持有命令对象,通常是多个,并通过访问命令对象来执行相关请求,他不直接访问接收者。
 */
public class Waiter {
    //命令对象
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void takeOrder() {
        // 服务员接收到顾客的点菜请求
        System.out.println("服务员接收到顾客(客户端)点菜请求!");
        // 执行点菜操作
        command.order();
    }

    public void cancelOrder() {
        // 服务员收到顾客的取消点菜请求
        System.out.println("服务员接收到顾客(客户端)取消点菜请求!");
        // 执行取消点菜操作
        command.cancelOrder();
    }
}

5.5 testCommand

/**
 * @author Created by njy on 2023/6/29
 * 命令模式测试类
 */
@SpringBootTest
public class TestCommand {

    @Test
    void testCommand(){
        // 创建厨师(接收者)
        Chef chef = new Chef();
        // 创建点菜命令
        Command orderCommand = new OrderCommand(chef);
        // 创建服务员(调用者)
        Waiter waiter = new Waiter();
        // 设置命令
        waiter.setCommand(orderCommand);
        // 服务员接收到点菜请求
        waiter.takeOrder();
        // 服务员接收到取消点菜请求
        waiter.cancelOrder();
    }
}

六、总结

命令模式适用于需要将请求封装成对象,实现请求发出者和接收者之间的解耦,并支持撤销、队列化和延迟执行的场景。它虽然可以提高系统的可扩展性和灵活性,但是需要权衡额外的开销和复杂性。

END:更多设计模式的介绍,推荐移步至 23种设计模式学习导航(Java完整版) 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_45433817/article/details/131465270

智能推荐

【2022最新Java面试宝典】—— SpringBoot面试题(44道含答案)_【2022最新java面试宝典】—— springboot面试题(44道含答案)_java spin-程序员宅基地

文章浏览阅读10w+次,点赞397次,收藏4.5k次。目录1. 什么是 Spring Boot?2. 为什么要用SpringBoot3. SpringBoot与SpringCloud 区别4. Spring Boot 有哪些优点?5. Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?6. Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?7. SpringBoot Starter的工作原理8. Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?9. SpringBoot支持什么前端模板,10. Spr_【2022最新java面试宝典】—— springboot面试题(44道含答案)_java spingboot 面

c#使用Region对图形区域构造和填充_region graphicspath 矩形 填充-程序员宅基地

文章浏览阅读2.7k次。 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Drawing._region graphicspath 矩形 填充

项目管理知识理论落地实践_pmp理论落地-程序员宅基地

文章浏览阅读459次。请大家原谅我消失了一年多,这一年半的时间在从事项目管理工作,积攒一年终于获得一定成果,拿来给大家分享。首先晒个绝版PMP 5A证书和考试成绩单,真的是绝版哦,因为后边就不再有5A的评价了^_-然后附上个人结合项目管理知识理论与实际项目经验整合的资料,包括了大家可能都会不易搞明白的理论落地实际的关键,以及一些从事项目管理必备的素材,如软开国家标准、阿里巴巴代码规范、高级项目管理师电子版书籍等。深度可能不够拔高,适合从事项目管理初期的人员参考,但绝对全!是本人整理后企业内部实行的版本,关键完全._pmp理论落地

ChatMind-人工智能AI生成思维导图-程序员宅基地

文章浏览阅读2k次。既能帮助用户快速总结分析,又能源源不断地提供创作灵感,致力为用户提供最优质的智能化思维导图方案,专注于 AI 生成思维导图的效率工具。小测一下直接输入一句话 / 问题,AI 自动生成了一份完整的思维导图,而且支持在线编辑,支持图片、SVG 和 MarkDown 等等格式导出。是什么 ChatMind,是一款利用与 AI 的对话中生成和编辑思维导图的工具,支持上下文改写扩充对话,ChatMind AI 可用于多种场景,例如记笔记、日程安排、感兴趣的大家可以去试一下,而且可以免费生成8条!_chatmind

龙芯1x嵌入式开发工具_龙芯1x嵌入式开发环境软件-程序员宅基地

文章浏览阅读1w次。龙芯1x嵌入式开发工具收藏一下:龙芯1x嵌入式开发工具|Loongson 1x Embedded Develo…|关于我们|龙芯嵌入式开发工具|苏州天晟软件龙芯嵌入式开发工具|苏州天晟软件,龙芯1x嵌入式开发工具是一套用于开发龙芯1系列芯片的RTThread/FreeRTOS/uCOS/RTEMS项目或裸机项目的嵌入式编程工具(首页内容),关于我们http://www.loongide.com/龙芯1x嵌入式开发工具是一套用于开发龙芯1系列芯片的RT-Thread/FreeRTOS/uCOS/ RT_龙芯1x嵌入式开发环境软件

HTTP1.0 1.1 2.0 HTTP和HTTPS结构区别 加密流程_http1.1帧结构-程序员宅基地

文章浏览阅读716次。此外,HTTPS用的是443端口,HTTP用的是80端口HTTP协议报文:请求报文和响应报文HTTP请求: 由四部分组成:请求行(含请求方法GET或POST,以及URL),请求头部,空行,请求数据请求头部:含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。例如 Accept:浏览器能接受的媒体类型;Accept-language:可接受的语言 ..._http1.1帧结构

随便推点

安全多方计算之十:联邦学习与安全多方计算-程序员宅基地

文章浏览阅读2.9k次,点赞14次,收藏15次。联邦学习和安全多方计算都是解决数据隐私保护问题的技术,两者既有联系又有区别。本文针对两种的基本概念、应用场景、区别与联系进行了详细介绍。_联邦学习与安全多方计算

Java 创建目录,移动文件,重命名文件名_java创建目录命名-程序员宅基地

文章浏览阅读327次,点赞6次,收藏2次。前言今天要使用Java File类,实现创建目录,移动文件,重命名文件名功能[email protected] public void mvFileTest() { String fileName = "test.txt"; // 目标文件目录 String cameraPath = "C:/develop/project/lmes/ftp_root/camera"; // 源文件 File sourceF_java创建目录命名

利用CSS3做简单的图片上下左右翻转_css img上下翻转-程序员宅基地

文章浏览阅读1.5w次,点赞2次,收藏5次。今天想在页面上加一点效果,所以就做了一个图片翻转 直接上代码吧:1.第一步肯定是在HTML页面上放入图片 <img class="transition" src="XXX.jpg" /></li>2.第二步骤就是在改元素下面添加一个transition,参数分别表示时间和移动的效果 .transition { -webkit-transi..._css img上下翻转

线性回归模型之最小二乘法(python实现)_python最小二乘法求回归方程-程序员宅基地

文章浏览阅读3.6k次,点赞7次,收藏22次。最小二乘法(Ordinary Least Square, OLS)是用数学公式直接求解线性回归方程的参数的方法。以最简单的一元线性回归为例,公式6-4中显示一系列的X值可以求出一系列的预测值Y’,的目的是使得每一对预测的Y’和Y之间的误差(Y- Y’)最小化。由于误差有正误差有负误差,为了避免彼此抵消,需要使用误差的平方来衡量。虽然绝对值也可以避免误差抵消,但是绝对值的代数计算性不如平方好,不便于求微分。二乘表示平方,最小二乘法就表示求误差平方和最小的方法。_python最小二乘法求回归方程

用java读取properites文件值,并且将值存入类变量(static )以方便获取_properties static-程序员宅基地

文章浏览阅读1.7k次。在实际开发中,可能需要拿到某个properties的值,如果不是经常使用,可以直接用inputStream=ZHRTActivityUrlUtils.class.getClassLoader().getResourceAsStream(ACTIVITY_FILENAME);properties.load(inputStream);但是比如把URL连接存到properties文件的时候,_properties static

顶会论文:深度学习检测网络安全漏洞报告的不一致性,你常用的CVE、NVD漏洞库信息可能不可靠_gsd cve-程序员宅基地

文章浏览阅读1.7k次。Usenix Security是信息安全领域“四大”顶级学术会议(此外还包括S&P,CCS,NDSS)之一,始于上世纪90年代初,每年涵盖的安全领域包含:二进制安全、固件安全、取证分析、Web安全、隐私保护、恶意分析、硬件保护、智能合约等。Usenix Security 被中国计算机学会(CCF)列为“网络与信息安全”A类会议。网络安全行业已经通过建立强大的社区来发现和修补漏洞。CVE(Common Vulnerabilities and Exposures,常见漏洞和泄露)和NVD(Na._gsd cve

推荐文章

热门文章

相关标签