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

设计模式(十九)----行为型模式之命令模式

1、概述

日常生活中,我们出去吃饭都会遇到下面的场景。

定义:

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、传递、调用、增加与管理。命令是相同的,而顾客服务员厨师这些对象是变化的。

2、结构

命令模式包含以下主要角色:

  • 抽象命令类(Command)角色: 定义命令的接口,声明执行的方法。

  • 具体命令(Concrete Command)角色:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

  • 实现者/接收者(Receiver)角色: 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

  • 调用者/请求者(Invoker)角色: 要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

3、案例实现

将上面的案例用代码实现,那我们就需要分析命令模式的角色在该案例中由谁来充当。

服务员: 就是调用者角色,由她来发起命令。

资深大厨: 就是接收者角色,真正命令执行的对象。

订单: 命令中包含订单。

类图如下:

代码如下:

//抽象命令类(Command)
public interface Command {void execute();//只需要定义一个统一的执行方法
}
//具体命令(Concrete  Command)角色
public class OrderCommand implements Command {
​//持有接受者对象private SeniorChef receiver;private Order order;
​public OrderCommand(SeniorChef receiver, Order order){this.receiver = receiver;this.order = order;}
​public void execute()  {System.out.println(order.getDiningTable() + "桌的订单:");Set<String> keys = order.getFoodDic().keySet();for (String key : keys) {receiver.makeFood(order.getFoodDic().get(key),key);}
​try {Thread.sleep(100);//停顿一下 模拟做饭的过程} catch (InterruptedException e) {e.printStackTrace();}
​
​System.out.println(order.getDiningTable() + "桌的饭准备完毕!!!");}
}
​
public class Order {// 餐桌号码private int diningTable;
​// 用来存储餐名并记录份数private Map<String, Integer> foodDic = new HashMap<String, Integer>();
​public int getDiningTable() {return diningTable;}
​public void setDiningTable(int diningTable) {this.diningTable = diningTable;}
​public Map<String, Integer> getFoodDic() {return foodDic;}
​public void setFoodDic(String name, int num) {foodDic.put(name,num);}
}
​
// 资深大厨类 是命令的Receiver
public class SeniorChef {
​public void makeFood(int num,String foodName) {System.out.println(num + "份" + foodName);}
}
​
//服务员类(属于请求者角色)
public class Waitor {
​private ArrayList<Command> commands;//可以持有很多的命令对象
​public Waitor() {commands = new ArrayList();}public void setCommand(Command cmd){commands.add(cmd);}
​// 发出命令 喊 订单来了,厨师开始执行public void orderUp() {System.out.println("美女服务员:叮咚,大厨,新订单来了.......");for (int i = 0; i < commands.size(); i++) {Command cmd = commands.get(i);if (cmd != null) {cmd.execute();}}}
}
​
public class Client {public static void main(String[] args) {//创建2个orderOrder order1 = new Order();order1.setDiningTable(1);order1.getFoodDic().put("西红柿鸡蛋面",1);order1.getFoodDic().put("小杯可乐",2);
​Order order2 = new Order();order2.setDiningTable(2);order2.getFoodDic().put("尖椒肉丝盖饭",1);order2.getFoodDic().put("小杯雪碧",1);
​//创建接收者SeniorChef receiver=new SeniorChef();//将订单和接收者封装成命令对象OrderCommand cmd1 = new OrderCommand(receiver, order1);OrderCommand cmd2 = new OrderCommand(receiver, order2);//创建调用者 waitorWaitor invoker = new Waitor();invoker.setCommand(cmd1);invoker.setCommand(cmd2);
​//将订单带到柜台 并向厨师喊 订单来了invoker.orderUp();}
}

测试结果

4、优缺点

1,优点:

  • 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。

  • 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。

  • 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。

  • 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

2,缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类,但是不会出现类爆炸的情况

  • 系统结构更加复杂。

5、使用场景

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。

  • 系统需要在不同的时间指定请求、将请求排队和执行请求。

  • 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

6、JDK源码解析

Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法

//命令接口(抽象命令角色)
public interface Runnable {public abstract void run();
}
​
//调用者
public class Thread implements Runnable {private Runnable target;public synchronized void start() {if (threadStatus != 0)throw new IllegalThreadStateException();
​group.add(this);
​boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {}}}private native void start0();
}

会调用一个native方法start0(),调用系统方法,开启一个线程。而接收者是对程序员开放的,可以自己定义接收者。例如:

/*** jdk Runnable 命令模式*      TurnOffThread : 属于具体*/
public class TurnOffThread implements Runnable{private Receiver receiver;public TurnOffThread(Receiver receiver) {this.receiver = receiver;}public void run() {receiver.turnOFF();}
}
/*** 测试类*/
public class Demo {public static void main(String[] args) {Receiver receiver = new Receiver();TurnOffThread turnOffThread = new TurnOffThread(receiver);Thread thread = new Thread(turnOffThread);thread.start();}
}

相关文章:

设计模式(十九)----行为型模式之命令模式

1、概述 日常生活中&#xff0c;我们出去吃饭都会遇到下面的场景。 定义&#xff1a; 将一个请求封装为一个对象&#xff0c;使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通&#xff0c;这样方便将命令对象进行存储、传递、调用、增加与管理。命…...

【数据库】数据库基础架构

数据库架构 数据库对于后端程序员来说是每天都需要打交道的系统&#xff0c;因此了解并掌握MySQL底层原理是必须的。 基础架构图 MySQL内部分为两层&#xff0c;一个是Server层&#xff0c;另一个是存储引擎层&#xff0c;而我们常用的就是MyISAM、InnoDB&#xff0c;主要负…...

English Learning - L2 语音作业打卡 双元音 [ɔɪ] [ɪə] Day16 2023.3.8 周三

English Learning - L2 语音作业打卡 双元音 [ɔɪ] [ɪə] Day16 2023.3.8 周三&#x1f48c;发音小贴士&#xff1a;&#x1f48c;当日目标音发音规则/技巧:&#x1f36d; Part 1【热身练习】&#x1f36d; Part2【练习内容】&#x1f36d;【练习感受】&#x1f353;元音 [ɔ…...

C++语法规则4(C++面向对象)

接口&#xff08;抽象类&#xff09; 接口描述了类的行为和功能&#xff0c;而不需要完成类的特定实现。C 接口是使用抽象类来实现的&#xff0c;抽象类与数据抽象互不混淆&#xff0c;数据抽象是一个把实现细节与相关的数据分离开的概念。 如果类中至少有一个函数被声明为纯虚…...

【Spring 深入学习】AOP的前世今生之后续

AOP的前世今生之后续 1. 概述 上篇文章【Spring 深入学习】AOP的前世今生之代理模式我们讲述了代理模式。而我们今天的主人公AOP就是基于代理模式实现的&#xff0c;所以我们今天会简单学习下AOP 2. 什么是AOP 是面向切面编程&#xff0c;一般可以帮助我们在不修改现有代码的情…...

软考高项——配置管理

配置管理配置管理配置管理6个主要活动配置项配置基线配置项的状态配置库配置库权限管理配置审计配置管理 配置管理的总线索包括&#xff1a; 1&#xff09;配置管理6个主要活动 2&#xff09;配置项 3&#xff09;配置基线 4&#xff09;配置项的状态 5&#xff09;配置库 6&a…...

网站SEO优化,网站TDK三大标签SEO优化,LOGO SEO优化

SEO&#xff08;Search Engine Optimization&#xff09;汉译为搜索引擎优化&#xff0c;是一种利用搜索引擎的规则提高网站在有关搜索 引擎内自然排名的方式。 SEO 的目的是对网站进行深度的优化&#xff0c;从而帮助网站获取免费的流量&#xff0c;进而在搜索引擎上提升网站的…...

select查询语句

worker表的字段有id, d_id, name, sex, birthday, salary, address 编号,部门号,姓名,性别,出生日期,工资,家庭住址 department表的字段有d_id, d_name, function, address 部门号,部门名,部门职能,部门位置 (1)查询worker表的所有记录(用*表示)。 select * fro…...

没有对象感,沟通太费劲

沟通中最重要的感觉&#xff1a;对象感&#xff01; 要沟通的是谁&#xff1f;以啥方式最好&#xff1f; 趣讲大白话&#xff1a;蹲着跟小孩说话 【趣讲信息科技100期】 ******************************* 对象感是沟通者必须训练和提升的 是换位思考的一种能力 以便跟沟通对象进…...

智能优化算法之遗传算法

该算法已被很多篇文章讲解&#xff0c;本文将会去除很多较简单的内容&#xff0c;挑选认为重点核心部分进行讲述&#xff0c;内容中有属于信息的收集整理部分&#xff0c;也有属于自己理解的部分。 1、遗传算法概述 遗传算法是一类借鉴生物界的进化规律演化而来的随机化搜索方…...

【rabbitmq 实现延迟消息-插件版本安装(docker环境)】

一&#xff1a;插件简介 在rabbitmq 3.5.7及以上的版本提供了一个插件&#xff08;rabbitmq-delayed-message-exchange&#xff09;来实现延迟队列功能。同时插件依赖Erlang/OPT 18.0及以上。 二&#xff1a;插件安装 1&#xff1a;选择适合自己安装mq 版本的插件&#xff1…...

【大数据】HDFS管理员 HaAdmin 集群高可用命令详细使用说明

高可用HaAdmin使用概览使用说明checkHealth查看NameNode的状态所有NN的服务状态查询指定NN的服务状态failovertransitionToActive概览 HDFS高可用特性解决了集群单点故障问题&#xff0c;通过提供了两个冗余的NameNode以主动或被动的方式用于热备&#xff0c;使得集群既可以从…...

京区航天研究所 哪些比较好的研究所?

第一梯队&#xff1a;一院一部、战术武器部、10所、12所、研发部、空天部&#xff0c;五院501所&#xff08;总体设计部&#xff09;、502所、通导部、遥感部、钱室&#xff08;所人均年薪35w-50w级别&#xff09; 第二梯队&#xff1a;一院14所、15所&#xff0c;二院未来实验…...

Nacos配置拉取及配置动态刷新原理【源码阅读】

Nacos配置拉取及配置刷新原理 一、初始化时获取配置文件 背景 SpringCloud项目中SpringBoot在启动阶段除了会创建SpringBoot容器&#xff0c;还会通过bootstrap.yml构建一个SpringCloud容器&#xff0c;之后会在准备上下文阶段通过SPI加载实现类后&#xff0c;会进行配置合并…...

第十届省赛——9等差数列(集合做法)

题目&#xff1a;试题 I: 等差数列时间限制: 1.0s 内存限制: 512.0MB 本题总分&#xff1a;25 分【问题描述】数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列&#xff0c;只记得其中 N 个整数。现在给出这 N 个整数&#xff0c;小明想知道包含这…...

《数据分析-JiMuReport03》JiMuReport报表设计入门介绍-新建报表

报表设计 1 新建报表 1.1 创建新的数据报表 以数据报表为例&#xff0c;简单介绍创建报表的过程 1.2 进入报表设计页面 如下图可见&#xff0c;主要分为四个模块&#xff1a; 模块一(左) 数据集管理报表信息数据字典 模块二(右) 这部分是对数据报表的进一步优化 模块三(上…...

从功能测试进阶自动化测试,爆肝7天整理出这一份超全学习指南【附网盘资源】

因为我最近在分享自动化测试技术&#xff0c;经常被问到&#xff1a;功能测试想转自动化&#xff0c;请问应该怎么入手&#xff1f;有没有好的资源推荐&#xff1f;那么&#xff0c;接下来我就结合自己的经历聊一聊我是如何在工作中做自动化测试的。&#xff08;学习路线和网盘…...

CNN神经网络——手写体识别

目录 Load The Datesets Defining,Training,Measuring CNN Algorithm Datasets GRAET HONOR TO SHARE MY KNOWLEDGE WITH YOU This paper is going to show how to use keras to relize a CNN model for digits classfication Load The Datesets The datasets files are …...

python调试模块ipdb

1. 调试python ipdb是用来python中用以交互式debug的模块&#xff0c;可以直接利用pip安装; 其功能类似于pycharm中 python控制台&#xff0c; 而使用ipdb 的优点&#xff0c;便是直接在代码中调试&#xff0c; 避免了在python控制台&#xff0c;或者重新设置一些简单变量。…...

【数据库】聊聊MySQL的日志,binlog、undo log、redo log

日志 在数据库中&#xff0c;如何保证数据的回滚&#xff0c;以及数据同步&#xff0c;系统宕机后可以恢复到原来的状态&#xff0c;其实就是依靠日志。 其中bin log是Server层特有的&#xff0c;redo log是Innodb存储引擎特有的。 bin log 是逻辑日志&#xff0c;主要记录这条…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

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

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

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

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

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

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...