毅四捕Go设计模式笔记——命令模式

news2024/12/23 10:37:58

命令模式(Command Pattern)

为了解决什么问题?

命令模式的目的是将请求发起者和请求执行者解耦,使得请求的发起者不需要知道具体的执行者是谁,也不需要知道执行的具体过程,只需要发送请求即可。

通过使用命令对象来封装请求,可以参数化和传递可调用的动作。同时,支持可撤销操作和队列请求等功能。

怎么用代码实现?

下面让我们通过一个餐厅下单的例子来看看怎么实现命令模式。例子里包含三个角色:

  • 顾客
  • 服务员
  • 厨师
    服务员在收到顾客的点餐请求后,然后将请求封装成命令,并交给厨师准备食物。

首先,定义好作为命令执行者的厨师,这里的厨师会制作汉堡包和沙拉。

/**
 * 厨师接收点菜的命令并开始烹饪
 */
public class Chef {
    public void makeBurger() {
        System.out.println("Chef is making a burger");
    }
    
    public void makeSalad() {
        System.out.println("Chef is making a salad");
    }
}

然后,定义抽象下单命令,以及具体的汉堡包和沙拉的下单命令。

public interface OrderCommand {
    void execute();
}

/**
 * 烹饪汉堡包的命令
 */
public class BurgerOrderCommand implements OrderCommand {
    @Override
    public void execute(Chef chef) {
        chef.makeBurger();
    }
}

/**
 * 准备沙拉的命令
 */
public class SaladOrderCommand implements OrderCommand {
    @Override
    public void execute(Chef chef) {
        chef.makeSalad();
    }
}

接着,定义服务员角色。

/**
 * 服务员是命令的调用者
 */
public class Waiter {
    private Chef chef;
    private OrderCommand orderCommand;
    
    public Waiter(Chef chef) {
        this.chef = chef;
    }
    
    public void sendOrderCommandToKitchen(OrderCommand orderCommand) {
        this.orderCommand = orderCommand;
        System.out.println("Waiter sending order to kitchen...");
        orderCommand.execute(chef);
    }
}

最后,顾客通过服务员下单,让厨师做出想吃的菜品。

/**
 * 餐厅顾客类
 */
public class RestaurantClient {
    public static void main(String[] args) {
        Chef chef = new Chef(); // 接收方
        Waiter waiter = new Waiter(chef); // 调用方

        OrderCommand burgerOrder = new BurgerOrderCommand(); // 顾客想吃汉堡
        waiter.sendOrderCommandToKitchen(burgerOrder); // 服务员收到顾客订单后,将订单发送至厨房

        OrderCommand saladOrder = new SaladOrderCommand(); // 顾客改主意,想吃沙拉
        waiter.sendOrderCommandToKitchen(saladOrder); // 服务员收到顾客订单后,将订单发送至厨房
    }
}

为什么可以解决这个问题?

命令模式通过将具体的请求封装成对象,使得发起请求的操作和接收请求的对象之间不直接发生依赖关系,从而实现请求发起者和请求执行者的解耦。

因为命令对象把请求封装成了对象,这使得你可以用不同的请求、队列或者日志来参数化其他对象,也可以支持撤销操作。

命令模式适用于哪些场景?

参数化对象:需要将请求参数化并传递给调用者时,可以使用命令模式。

操作排队:需要将请求排队执行,例如任务队列、线程池等。

支持撤销操作:需要提供撤销和恢复请求功能的场景。

支持宏命令:可以使用命令模式组合多个命令,实现宏命令的功能。

命令模式在开源代码中比较场景,下面是典型的案例:

Swing中的Action:Java Swing库中,javax.swing.Action接口代表了一个抽象的用户界面动作,它本身就是命令模式的一种实现。

Guava的事件总线:Guava库中的事件总线(EventBus)可以结合命令模式使用,发布者发布命令事件,而订阅者则执行相关的命令。

命令模式把发送命令的责任和执行命令的责任分开,确保了系统设计的灵活性和扩展性。此外,它还简化了其他对象的逻辑,因为它们不需要知道实际的执行逻辑。这一模式特别适用于实现撤销(redo)/恢复(undo)操作、事务系统等需要定义、存储、传递和执行请求的场合。

———————————这是分割线———————————

欢迎添加博主vx深入交流:
博主微信

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

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

相关文章

使用 LooperPrinter 监控 Android 应用的卡顿

在 Android 开发中,主线程(UI线程)的卡顿直接影响用户体验。LooperPrinter 是一种有效的工具,可以帮助我们监测和识别这些卡顿。下面是如何实现 LooperPrinter 监控的详细步骤和相应的 Kotlin 代码示例。 步骤 1: 创建自定义的 P…

人脸识别开源算法库和开源数据库

目录 1. 人脸识别开源算法库 1.1 OpenCV人脸识别模块 1.2 Dlib人脸识别模块 1.3 SeetaFace6 1.4 DeepFace 1.5 InsightFace 2. 人脸识别开源数据库 2.1 CelebA 2.2 LFW 2.3 MegaFace 2.4 Glint360K 2.5 WebFace260M 人脸识别 (Face Recognition) 是一种基于人的面部…

2024年十五届蓝桥杯省赛大学B组真题(Java完整版)

2024年十五届蓝桥杯省赛大学B组真题(Java) 前言: 赛后一直犹豫要不要对比赛进行复盘出个题解,拖到了现在,终于也是等到比赛结果出来,看到没有辜负个人期望成功取得省一,决定在国赛前对省赛进行…

记录k8s以docker方式安装Kuboard v3 过程

原本是想通过在k8s集群中安装kuboad v3的方式安装kuboard,无奈在安装过程中遇到了太多的问题,最后选择了直接采用docker安装的方式,后续有时间会补上直接采用k8s安装kuboard v3的教程。 1.kuboard安装文档地址: 安装 Kuboard v3 …

外观模式【结构型模式C++】

1.概述 外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。 2.结构   外观角色(Facade):为多个子系统对外提供一个共同的接口,知道哪些子系统负责处理请求,将客户端的请…

Python使用设计模式中的建筑模式将数据写入Excel且满足条件内容标红

对于这个任务,适合使用"Builder"设计模式。Builder模式的主要目的是将对象的构建与其表示分离,以便相同的构建过程可以创建不同的表示。在这个情况下,我们需要一个构建器来逐行构建Excel表格,并根据给定的数据添加相应的…

MySQL--对于库的操作对于表的操作

一、库的查看创建删除 库的查看 show databases; 库的创建(创建一个test1数据库) create database test1; 同样,我们另起一个root会话,并执行 cd /var/lib/mysql 然后发现多了一个test1目录 删除库(删除test1数…

Java 为什么设计成 “String” 不能用 “==” 比较值?

Java中的String是一种特殊的对象类型,用于表示字符串。在Java中,String对象的创建和比较是一个重要的话题,其中,操作符在比较String对象时有着特殊的行为。为了了解Java为什么设计成String不能用比较值,需要深入探讨Ja…

VMamba原理

为了解决模型中的方向敏感性问题,我们引入了交叉扫描模块(CSM)。该模块能够遍历图像空间域,将任意视觉图像转化成有序序列。 VMamba降低注意力机制复杂度的概念来源于“具有选择性的扫描状态空间序列模型”(Selective…

力扣33. 搜索旋转排序数组

Problem: 33. 搜索旋转排序数组 文章目录 题目描述思路复杂度Code 题目描述 思路 1.初始化左右指针:首先,定义两个指针left和right,分别指向数组的开始和结束位置。 2.计算中间值:在left和right之间找到中间位置mid。 3.比较中间值…

人工智能分割分类model:nnUnet-paddle

文章目录 神经网络nnUnet和paddle都需要在Ubuntu下进行安装PaddleProject 神经网络 开源来自https://github.com/MIC-DKFZ/nnUNet 自建了仓库,但还不会用 来自 mmsegmentation有空去了解 . MICCAI 2020 也是用到这个网络 paddle上的是不是不能用… nnUnet和pad…

废旧锂电池污水如何处理

废旧锂电池中含有多种潜在有害物质,因此正确处理废旧锂电池产生的污水对环境保护至关重要。以下是处理这种污水的几个关键步骤: 收集与预处理: 废旧锂电池应首先在干燥、通风良好的环境中安全收集,避免污水泄漏。在开始处理之前&…

Ansible-Tower安装破解

主机IP地址版本Ansible192.168.169.2042.9.1Tower192.168.169.2043.6.2 基础环境 systemctl disable firewalld --now && setenforce 0 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config mv /etc/yum.repos.d/CentOS-* /tmp/ curl -o /etc/yum.repo…

【UE5】动态播放媒体

最近项目中有一个需求,需要将场景中的42块屏幕都显示媒体内容,想着如果每一块屏幕都创建一个MediaPlayer资产、一个MediaSource资产、一个MediaTexture资产及创建对应的Material,就是4*42168个资产需要维护了,所以想着就全部采用动…

数据库|TiDB-Server API的高效应用指南

一、API介绍 1.Status 显示TiDB 连接数、版本和git_hash 信息 tidb-server_ip:status_port/status { "connections": 0, "version": "5.7.25-TiDB-v6.1.1", "git_hash": "5263a0abda61f102122735049fd0dfadc7b7f822" } 2.St…

C语言:文件操作(中)

片头 嗨!小伙伴们,大家好!在上一篇中,我们学习了C语言:文件操作(上),在这一篇中,我们将继续学习文件操作,准备好了吗?Ready Go ! ! ! 文件的顺序…

宽字符的来历:从ASCII到Unicode,C语言中的宽字符处理

目录 一、ASCII编码:字符世界的开篇 二、Unicode与宽字符的诞生 宽字符类型与宽字符串 三、C语言中的宽字符处理函数 四、宽字符与多字节字符 结语 在计算机科学的发展历程中,字符编码经历了从简单到复杂、从单一语言到全球多语种支持的演变过程。…

【AGX】Ubuntu20.04 + ROS_ noetic+ 大疆Mid360激光 雷达评测

大家好,我是虎哥,最近组装机器人,使用到了大疆孵化的圳市览沃科技有限公司(简称Livox览沃科技)推出的觅道系列全新混合固态激光雷达Mid-360,顺便试试效果,也记录一下使用入门过程。 "觅道M…

323_C++_QT_使用QProcess执行cmd解压tar.gz等等其他压缩包文件到指定目录,不需要外部库,QT自带API的就行

// decompressPath : 解压到此目录 // fileName : 解压的tar.gz文件名executeCommand(decompressPath , QString::fromStdString(fileName));// 开始解压 void executeCommand

基于Springboot的医疗服务系统

基于SpringbootVue的医疗服务系统设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录 首页 公告信息 医疗地图 医疗药品 普通村民管理 乡村医生管理 公告信息管理 乡村诊…