当前位置: 首页 > 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;主要记录这条…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

Python 实现 Web 静态服务器(HTTP 协议)

目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1&#xff09;下载安装包2&#xff09;配置环境变量3&#xff09;安装镜像4&#xff09;node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1&#xff09;使用 http-server2&#xff09;详解 …...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...

【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权

摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题&#xff1a;安全。文章将详细阐述认证&#xff08;Authentication) 与授权&#xff08;Authorization的核心概念&#xff0c;对比传统 Session-Cookie 与现代 JWT&#xff08;JS…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...