当前位置: 首页 > news >正文

命令模式-请求发送者与接收者解耦

 去小餐馆吃饭的时候,顾客直接跟厨师说想要吃什么菜,然后厨师再开始炒菜。去大点的餐馆吃饭时,我们是跟服务员说想吃什么菜,然后服务员把这信息传到厨房,厨师根据这些订单信息炒菜。为什么大餐馆不省去这个步骤,像小餐管那样点菜呢?原因主要有以下几点:

  1. 提供效率。厨师专注炒菜就行,而不必花时间跟客户接触。
  2. 各司其职,提高服务质量。厨师擅长炒菜,而服务员擅长跟顾客打交道。
  3. 使工作有条不紊的进行。不会像小餐馆那样,来了个新客户,需要马上停止炒菜,去招呼客人,而另一边客户要在催着上菜。
  4. 阻断客户与厨师的接触。客户无须知道炒菜的厨师是谁,厨师也不需要知道他为谁炒的菜。

在这里,服务员发挥着“命令”的作用,将客户的命令传递给厨师,厨师做出相应。而这种模式是一种“命令模式”。

1 命令模式概述

引入一个命令类,通过命令类来降低发送者和接收者的耦合度。将一个请求封装成一个命令对象,发送者只需指定一个命令对象,再通过命令对象来调用请求接收者的处理方法。

图 命令模式结构图

Command:抽象命令类,一般是抽象类或接口。声明了用于执行请求的execute()等方法,通过这些方法可调用请求接收者相关操作。

ConcreteCommand:具体命令类,对应具体接收者对象,维护了一个接收者对象的引用,在实现execute()方法时,将调用接收者对象的相关操作(action()方法等)。

Invoker:调用者,即请求发送者。通过命令对象来执行请求。

Reciver:接收者,执行与请求相关的操作,具体实现对请求的业务处理。

public interface Command {String getName();void makeOrder(String name);}public class WaiterCommand implements Command{private final String name;private CookReceiver cookReceiver;public WaiterCommand(String name, CookReceiver cookReceiver) {this.name = name;this.cookReceiver = cookReceiver;}public void setCookReceiver(CookReceiver cookReceiver) {this.cookReceiver = cookReceiver;}@Overridepublic String getName() {return name;}@Overridepublic void makeOrder(String name) {System.out.print("  " + cookReceiver.getName() + ":");cookReceiver.cooking(name);}}
public class CookReceiver {private final String name;public CookReceiver(String name) {this.name = name;}public String getName() {return name;}public void cooking(String name) {System.out.println("开始做菜:" + name);}}
public class CustomerInvoker {private Command waiter;public CustomerInvoker(Command waiter) {this.waiter = waiter;}public void changeWaiter(Command waiter) {this.waiter = waiter;}public void makeOrder(String name) {System.out.print(waiter.getName() + "为客户下单");waiter.makeOrder(name);}}
public class Client {private final static List<Command> waiterList = new ArrayList<>();static {CookReceiver cook1 = new CookReceiver("黄师傅");CookReceiver cook2 = new CookReceiver("刘师傅");waiterList.add(new WaiterCommand("小李",cook1));waiterList.add(new WaiterCommand("小张",cook2));waiterList.add(new WaiterCommand("小王", cook1));}public static void main(String[] args) {String[] menu = {"辣椒炒肉","剁椒鱼头","清蒸豆腐","爆炒花甲","酸辣螺蛳粉"};Random random = new Random();for (int i = 0; i < 6; i++) {CustomerInvoker invoker = new CustomerInvoker(waiterList.get(random.nextInt( waiterList.size())));invoker.makeOrder(menu[random.nextInt(menu.length)]);System.out.println("--------------");}
//        运行结果:
//        小王为客户下单  黄师傅:开始做菜:酸辣螺蛳粉
//        --------------
//        小王为客户下单  黄师傅:开始做菜:辣椒炒肉
//         --------------
//        小张为客户下单  刘师傅:开始做菜:剁椒鱼头
//        --------------
//        小张为客户下单  刘师傅:开始做菜:爆炒花甲
//        --------------
//        小王为客户下单  黄师傅:开始做菜:辣椒炒肉
//        --------------
//        小王为客户下单  黄师傅:开始做菜:酸辣螺蛳粉
//        --------------}}

命令模式的本质是对请求进行封装,一个请求对应一个命令。将发送命令与执行命令分割开,但不能减少类的数量。

1.1 命令队列

一个请求发送者发送一个请求时,不止一个请求接收者产生响应,这些接收者将逐个执行业务方法,完成对请求的处理。

图 命令队列结构图

2 优缺点

优点:

  1. 降低系统的耦合度,请求者与接收者之间完全解耦,相同的请求者可对应不同的接收者。同样,相同的接收者也也可以供不同的请求者使用,两者具有良好的独立性。
  2. 新的命令可用很容易地加入系统中。增加新的具体命令不会影响其他类,符合开闭原则。
  3. 笔记容易设计一个命令队列或宏命令。
  4. 为请求的撤销和恢复操作提供了一种设计和实现方案。

缺点:

1)会导致系统有过多的具体命令类。

3 适用场景

  1. 需要将请求调用者和请求接收者解耦。
  2. 系统需要支持命令的撤销和恢复操作。
  3. 需要将一组操作组合在一起形成宏命令。
  4. 需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以有不同的生命期。即最初的请求发出者可能已经不在了,而命令对象本身仍然是活动的。可以通过该命令对象去调用请求接收者,而无须关系请求调用者的存在性,可以通过请求日志等机制来具体实现。

相关文章:

命令模式-请求发送者与接收者解耦

去小餐馆吃饭的时候&#xff0c;顾客直接跟厨师说想要吃什么菜&#xff0c;然后厨师再开始炒菜。去大点的餐馆吃饭时&#xff0c;我们是跟服务员说想吃什么菜&#xff0c;然后服务员把这信息传到厨房&#xff0c;厨师根据这些订单信息炒菜。为什么大餐馆不省去这个步骤&#xf…...

【雕爷学编程】Arduino动手做(186)---WeMos ESP32开发板

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…...

3、JSON数据的处理

3.1 介绍 JSON数据 Spark SQL can automatically infer the schema of a JSON dataset and load it as a DataFrame Spark SQL能够自动将JSON数据集以结构化的形式加载为一个DataFrame This conversion can be done using SparkSession.read.json on a JSON file 读取一个JSO…...

8月5日上课内容 nginx的优化和防盗链

全部都是面试题 nginx的优化和防盗链 重点就是优化&#xff1a; 每一个点都是面试题&#xff0c;非常重要&#xff0c;都是面试题 1、隐藏版本号&#xff08;重点&#xff0c;一定要会&#xff09; 备份 cp nginx.conf nginx.conf.bak.2023.0805 方法一&#xff1a;修改配…...

网络爬虫请求头中的Referer和User-Agent与代理IP的配合使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8EJgMcgK-1691050515642)(https://cdn.nlark.com/yuque/0/2023/png/1313150/1691048724422-2a76d7b8-3ec3-48b7-9aec-d609d09b16d4.png#averageHue%2385b0a7&clientIdu3856fd20-7701-4&fromui&…...

RabbitMQ 生产者-消息丢失 之 场景分析

生产者-消息丢失 之 场景分析 生产者消息丢失的场景消息无法到达RabbitMQ连接断开信道关闭 RabbitMQ无法将消息入队交换机不存在无匹配队列 消息过期丢失消息丢失场景对比 生产者消息丢失的场景 生产者发送消息的流程如下&#xff1a;首先生产者和RabbitMQ服务器建立连接&…...

Hyper实现git bash在windows环境下多tab窗口显示

1.电脑上安装有git bash 下载链接&#xff1a;https://gitforwindows.org/ 安装Hyper 下载链接:官网 https://hyper.is/ 或者在百度云盘下载&#xff1a; https://pan.baidu.com/s/1BVjzlK0s4SgAbQgsiK1Eow 提取码&#xff1a;0r1f 设置 打开Hyper&#xff0c;依次点左上角-&g…...

Matlab的信号频谱分析——FFT变换

Matlab的信号频谱分析——FFT变换 Matlab的信号频谱分析 FFT是离散傅立叶变换的快速算法&#xff0c;可以将一个时域信号变换到频域。 有些信号在时域上是很难看出什么特征的。但是如果变换到频域之后&#xff0c;就很容易看出特征了。 这就是很多信号分析采用FFT变换的原因…...

如何从 Android 设备恢复已删除的文件?

从 Android 设备恢复已删除的文件很简单&#xff0c;但您需要了解内部恢复和SD 卡恢复之间的区别。 目前销售的大多数 Android 设备都配备了 SD 卡插槽&#xff08;通常为 microSD&#xff09;&#xff0c;可以轻松添加额外的存储空间。该存储空间可用于存储照片、视频、文档&a…...

servlet生命周期和初始化参数传递

servlet生命周期和初始化参数传递 1、servlet生命周期 只有第一次访问才会初始化&#xff0c;之后访问都只执行service中的。 除非tomcat关闭重新启动&#xff1a; 2、初始化参数传递...

dvwa靶场通关(十一)

第十一关&#xff1a;Reflected Cross Site Scripting (XSS) low 这一关没有任何防护&#xff0c;直接输入弹窗 <script>alert(xss)</script> 打开网页源代码&#xff0c; 从源代码中我们可以看到&#xff0c;前面是输出的第一部分Hello&#xff0c;我们输入的脚…...

【Spring】使用注解存储Bean对象

目录 一、配置扫描路径&#xff08;使用注解的方式存对象的前提&#xff09; 二、使用类注解存储Bean对象 1、使用五大类注解存储Bean对象 2、为什么要这么多的类注解&#xff1f; 2.1、五大类注解之间的关系 3、获取Bean对象时的默认命名规则 三、使用方法注解来存储…...

怎么维护好自己的电脑

你的电脑已经成为你工作、学习、娱乐的最佳工具之一&#xff0c;但是如果你不做好电脑维护工作&#xff0c;就可能面临着电脑变慢、蓝屏、崩溃等问题。在这篇文章中&#xff0c;我们将介绍10个电脑维护步骤&#xff0c;让你的电脑更加稳定&#xff01; 为什么需要电脑维护&…...

vscode中无法使用git解决方案

1 首先查看git安装目录 where git 2 找到bash.exe 的路径 比如&#xff1a;C:/Users/Wangzd/AppData/Local/Programs/Git/bin/bash 3 找到vscode的配置项setting.json 4 添加 "terminal.integrated.shell.windowns": "C:/Users/Wangzd/AppData/Local/Pr…...

MybatisPlus-CRUD,不带条件构造器的常用方法

mapper层 Repository public interface UserMapper extends BaseMapper<User> BaseMapper中封装好了增删改查的方法 后面直接调用就好了 测试类 SpringBootTest public class CrudTest {Autowiredprivate UserMapper userMapper;//新增Testpublic void insert(){//没…...

软件测试面试【富途面经分享】

目录 一面面经&#xff08;1h&#xff09; 二面面经 一面面经&#xff08;1h&#xff09; 一、对白盒黑盒灰盒测试的理解 答&#xff1a; 1、黑盒测试就当整个程序是个黑盒子&#xff0c;我们看不到它里面做了什么事情&#xff0c;只能通过输入输出看是否能得到我们所需的来…...

antd 库的 Table 组件中删除一个或多个选中的列表

先解释一下原代码每个方法的含义 const TablePage: React.FC () > {/* selectedRowKeys 指定选中项的 key 数组&#xff0c;需要和 onChange 进行配合在此处&#xff0c;通过 rowSelection.selectedRowKeys 来控制选中项。*/const [selectedRowKeys, setSelectedRowKeys] …...

针对java程序员的了解细节操作系统与进程

一、&#x1f49b; 操作系统&#xff08;浅浅概念&#xff09;&#xff1a;是用来搞管理软件的 1.对下,要管理各种硬件设备 2.对上,要给应用程序提供一个稳定的运行环境 二、&#x1f499; 进程&#xff1a;正在运行的程序&#xff0c;假如程序没有运行就不叫程序&#xff0c;…...

判定是否互为字符重排、回文排列

题1&#xff1a;判定是否互为字符重排 给定两个由小写字母组成的字符串 s1 和 s2&#xff0c;请编写一个程序&#xff0c;确定其中一个字符串的字符重新排列后&#xff0c;能否变成另一个字符串。 输入: s1 "abc", s2 "bca" 输出: true 输入: s1 &quo…...

QT QTextCharFormat 说明和使用

QTextCharFormat&#xff1a;设置文本编辑框字体&#xff0c;字号&#xff0c;加粗&#xff0c;倾斜&#xff0c;下划线&#xff0c;颜色 QTextCharFormat 类的一些常用属性和方法&#xff1a; setFont(const QFont &font): 设置字体。 setFontFamily(const QString &a…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...