14、设计模式之命令模式(Command)

news2024/11/18 14:02:33

一、什么是命令模式
命令模式(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),它定义了点菜和取消点菜的方法

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

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

/**
 * 
 * 2.接收者(Receiver):厨师
 * 定义:执行实际命令的类,命令对象会调用接收者的方法来执行请求。
 */
public class Chef {
 
    public void cook() {
        System.out.println("厨师执行点菜命令:正在烹饪菜品...");
    }
 
    public void cancelCooking() {
        System.out.println("厨师执行取消命令:停止烹饪菜品!");
    }
}

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

/**
 * 
 * 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

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

/**
 *
 * 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

/**
 * 
 * 命令模式测试类
 */
@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();
    }
}

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

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

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

相关文章

蓝桥杯-粘木棍-DFS

题目 思路 --有n根木棍,需要将其粘成m根木棍,并求出最小差值,可以用DFS枚举出所有情况。粘之前有n根短木棍,粘之后有m根长木棍,那么让长木棍的初始长度设为0。外循环让所有的短木棍都参与粘,内循环让要粘的…

基于SpringBoot的“企业客户信息反馈平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“企业客户信息反馈平台”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 平台首页界面图 技术文档界面图 问题信息…

C# Onnx C2PNet 图像去雾 室外场景

目录 介绍 效果 模型信息 项目 代码 下载 C# Onnx C2PNet 图像去雾 室外场景 介绍 github地址:https://github.com/YuZheng9/C2PNet [CVPR 2023] Curricular Contrastive Regularization for Physics-aware Single Image Dehazing 效果 模型信息 Model P…

专升本 C语言笔记-03 变量的作用域

1.变量的概念 内存中有个存储区域,这个地方的数据可以在同一类型范围内不断变化通过变量名,可以访问这块内存区域,获取里面的值; 变量名的构成:数据类型 变量名 值 C语言中变量声明格式: 数据类型 变量名 值 2.变量的注意 2.1.全局变量: 定义在函数外部的叫全局变量…

SD-WAN技术如何保障网络的持续连接和稳定性

在当今数字化时代,企业对于网络的稳定性和持续连接性需求日益增加。SD-WAN作为一种新兴的网络解决方案,为企业提供了有效的方式来实现网络的持续连接和稳定性。本文将探讨SD-WAN技术如何保障网络的持续连接和稳定性。 1、多路径冗余技术 SD-WAN采用了多…

一台服务器部署两个独立的mysql实例

🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 🏅阿里云开发者社区专…

激活函数Mish

paper:Mish: A Self Regularized Non-Monotonic Activation Function official implementation:https://github.com/digantamisra98/Mish 背景 在早期文献中,Sigmoid和TanH激活函数被广泛使用,随后在深度神经网络中失效。相比于…

大宗电子盘商品撮合制交易软件PHP后台

大宗电子盘商品撮合制交易软件是一种用于大宗商品电子交易的系统,其中撮合制是交易机制的核心部分,它负责将买卖双方的订单进行匹配并完成交易。在开发这类软件的PHP后台时,需要考虑以下几个关键方面: 系统架构设计: …

Docker拉取镜像存储不足

在使用Docker时,我们经常遇到一个问题,就是拉取镜像时提示存储空间不足。这是因为Docker在拉取镜像时需要将镜像文件下载到本地存储中,而有时本地存储空间不足以容纳完整的镜像文件。 本文将介绍一些解决这个问题的方法,并提供相…

云原生消息流系统 Apache RocketMQ 在腾讯云的大规模生产实践

导语 随着云计算技术的日益成熟,云原生应用已逐渐成为企业数字化转型的核心驱动力。在这一大背景下,高效、稳定、可扩展的消息流系统显得尤为重要。腾讯云高级开发工程师李伟先生,凭借其深厚的技术功底和丰富的实战经验,为我们带…

深入解析Java中锁机制以及底层原理

一、概述 1.1 背景 概念:锁是多线程编程中的机制,用于控制对共享资源的访问。可以防止多个线程同时修改或读取共享资源,从而保证线程安全。 作用:锁用于实现线程间的互斥和协调,确保在多线程环境下对共享资源的访问顺…

如何处理Android悬浮弹窗双击返回事件?

目录 1 前言 1.1 准备知识 1.2 问题概述 2 解决方案 3 代码部分 3.1 动态更新窗口焦点 3.2 窗口监听返回事件 3.3 判断焦点是否在窗口内部 3.4 窗口监听焦点移入/移出 1 前言 1.1 准备知识 1)开发环境: 2D开发环境:所有界面或弹窗…

FFmpeg工作流程及视频文件分析

FFmpeg工作流程: 解封装(Demuxing)--->解码(Decoding)--->编码(Encoding)--->封装(Muxing) FFmpeg转码工作流程: 读取输入流--->音视频解封装--->解码音视频帧--->编码音视频帧--->音视频封装--->输出目标流 可简单理解为如下流程: 读文件-->解…

教师如何搭建学生查询考试分数的平台?

随着信息技术的快速发展,搭建一个学生查询考试分数的平台已经成为现代教育管理的重要组成部分。这样的平台不仅可以提高成绩管理的效率,还能为学生提供便捷、及时的成绩查询服务。那么,作为教师,我们应该如何搭建这样一个平台呢&a…

计算机网络期末98+冲刺笔记

一、计算机网络基础 1.1计算机网络的概述 计算机网络的定义:利用通信设备和线路,将地理位置不同的具有独立功能的多台计算机机器外部设备连接起来,在网络操作系统、网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息…

力扣977. 有序数组的平方

思路:暴力法:全部平方,然后调用排序API,排序算法最快是N*log(N)时间复制度。 双指针法:要利用好原本的数组本就是有序的数组这个条件, 只是有负数 导致平方后变大了,那么平方后的最大值就是在两…

YOLOv5+DeepSort的汽车流量统计

前言 先来看下实现效果: 上图展示了用yolov5作为检测器,DeepSort为追踪器实现了对车流量的统计并绘制了每辆车的运行轨迹。 一、整体目录结构 下图展示了项目的整体目录结构: 其中: deep_sort文件下为目标跟踪相关代码&#x…

力扣串题:验证回文串2

bool judge(char *s,int m,int n){while(m<n){if(s[m]!s[n]){return false;}m,n--;}return true; } bool validPalindrome(char * s){for(int i0,jstrlen(s)-1;i<j;i,j--){if(s[i]!s[j]){return (judge(s,i1,j)||judge(s,i,j-1));}}return true; }这个题直接背大佬代码吧…

记录一下在Pycharm中虚拟环境的创建

如果在Pycharm中要新建一个虚拟环境&#xff0c;那你可以在Terminal中选择Command Prompt&#xff0c;在这里面执行相关命令 一、安装了Anaconda&#xff0c;创建虚拟环境 当你使用解释器是Anaconda提供的时&#xff0c;你可以使用conda命令执行&#xff0c;见以下操作&#x…

自适应窗口图片轮播HTML代码

自适应窗口图片轮播HTML代码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 代码下载地址 自适应窗口图片轮播HTML代码