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

一、什么是命令模式
命令模式(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 {@Testvoid testCommand(){// 创建厨师(接收者)Chef chef = new Chef();// 创建点菜命令Command orderCommand = new OrderCommand(chef);// 创建服务员(调用者)Waiter waiter = new Waiter();// 设置命令waiter.setCommand(orderCommand);// 服务员接收到点菜请求waiter.takeOrder();// 服务员接收到取消点菜请求waiter.cancelOrder();}
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论坛管理系统|基于Spring Boot+ Mysql+Java+B/S架构的论坛管理系统设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 l…

【Swing】Java Swing实现省市区选择编辑器

【Swing】Java Swing实现省市区选择编辑器 1.需求描述2.需求实现3.效果展示 系统:Win10 JDK:1.8.0_351 IDEA:2022.3.3 1.需求描述 在公司的一个 Swing 的项目上需要实现一个选择省市区的编辑器,这还是第一次做这种编辑器&#xf…

mysql生成连续的日期

1.代码 例如:生成"2023-03-01"至"2023-03-10"之间的日期 WITH RECURSIVE date_range AS (SELECT "2023-03-01" AS date FROM dualUNION ALLSELECT DATE_ADD(date, INTERVAL 1 DAY) dateFROM date_rangeWHERE DATE_ADD(date, INTER…

基于大数据的商业模式创新研究

目录 一、导论 2 (一)研究背景 2 (二)研究意义 2 (三)研究内容 3 (四)研究思路与研究方法 4 (五)国内外研究现状 6 二、大数据的界定与应用概况 7 &#xff…

数字逻辑-时序逻辑电路一

一、实验目的 (1)熟悉触发器的逻辑功能及特性。 (2)掌握集成D和JK触发器的应用。 (3)掌握时序逻辑电路的分析和设计方法。 二、实验仪器及材料 三、实验内容及步骤 1、用D触发器(74LS74&am…

Elastic Stack--09--ElasticsearchRestTemplate

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 spring-data-elasticsearch提供的APIQueryBuildersElasticsearchRestTemplate 方法ElasticsearchRestTemplate ---操作索引 ElasticsearchRestTemplate ---文档操作…

【数据结构七】堆与PriorityQueue详解

堆 在Java中有一种数据结构基于队列,并保证操作的数据带有优先级,该数据结构应该提供了两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。它的底层使用了堆这种数据结…

Ajax(2)

图片上传 传图片文件不能像传文字一样用JSON格式,可以用form-data类型携带文件 1.获取图片文件对象 2.使用FormData(浏览器内置的构造函数)携带图片文件 3.提交表单数据到服务器,返回图片网址 这里可能用到的事件监听器&#…

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

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

SpringCloud Gateway 新一代网关

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第六篇,即介绍 Gateway 新一代网关。 二、概述 2.1 Gateway 是什么 Gateway 是在 Spring 生…

【05】消失的数字

hellohello~这里是土土数据结构学习笔记🥳🥳 💥个人主页:大耳朵土土垚的博客 💥所属专栏:C语言函数实现 感谢大家的观看与支持🌹🌹🌹 有问题可以写在评论区或者私信我哦…

力扣506——和为K的子数组

https://leetcode.cn/problems/subarray-sum-equals-k/?envTypestudy-plan-v2&envIdtop-100-liked 1. 用到了前缀和的概念: 给定一个数组nums,从该数组的初始位置元素开始相加,前缀和数组 prefixSum 的第 i 个元素表示从数组开头到第 …