目录

1、介绍

1.1、命令模式定义

1.2、对比

1.3、典型应用场景

2、命令模式的结构

2.1、组成部分:

2.2、整体流程

3、实现

3.1、没有命令模式

3.2、命令模式写法

4、命令模式的优缺点


前言

java设计模式分类:


1、介绍

1.1、命令模式定义

     命令模式(Command Pattern)是一种行为型设计模式,又叫动作模式或事务模式

        它将请求(命令)封装成对象,使得可以用不同的请求对客户端进行参数化具体的请求可以在运行时更改、排队或记录,它将发出者和接收者解耦(顺序:发出者-->命令-->接收者)。

总结:

        把请求的动作和请求的接收者进行解耦,让你能将动作封装成对象,再传递、存储、撤销或排队等。

1.2、对比

状态模式:

Context(电梯)-- 持有当前状态 --> State(状态接口)-- 实现 --> OpenState, RunState等

命令模式:

1.3、典型应用场景

1、Runnable接口:

        Java中的Runnable接口就是一个典型的命令模式的应用。Runnable接口封装了需要执行的任务,然后可以交给线程去执行


2、Timer和TimerTask类:

        这两个类用于定时任务调度,TimerTask类封装了要执行的任务,然后由Timer类作为调用者执行这些任务。


3、Statement接口:

        在Java中与数据库交互时,SQL语句被封装成Statement对象,然后由数据库驱动程序执行相应的命令。

生活示例:

1、 餐厅点餐:

        在一家餐厅中,服务员充当调用者,厨师充当接收者,菜品可以作为具体命令。当顾客想点菜时,服务员会将顾客的需求封装成一个命令对象,并传递给厨师。厨师根据命令对象中的信息来完成相应的烹饪工作。这样,顾客和厨师之间不需要直接沟通,而是通过命令对象来实现点餐和烹饪的解耦。


2、遥控器控制家电:

        拿电视遥控器举例,遥控器是调用者,电视是接收者。每个按键都可以看作是一个具体命令,例如音量加、音量减、切换频道等。

        当用户按下某个按键时,遥控器会发送相应的命令给电视,然后电视根据命令执行相应的操作,如增加音量、减小音量或切换频道。


2、命令模式的结构

2.1、组成部分:

  1. Command(命令接口/抽象类) 声明execute()方法。
  2. ConcreteCommand(具体命令) 实现Command,并持有Receiver引用,把请求操作的接收者封装进来,调用接收者的方法。
  3. Receiver(接收者) 真正执行业务逻辑的对象。
  4. Invoker(调用者) 有个成员变量保存Command,并执行command.execute()
  5. Client(客户端): 组装命令、接收者、并给调用者下令。

2.2、整体流程

所有的“做某件事”,都变成订单(命令对象)Waiter只“发订单”,Chef只“实现订单”:

如下图所示:

        命令模式,把“执行动作”的代码封装成对象。Waiter(服务员)不需要知道每个命令详情,只要保存一份“命令单子”,然后调用它的执行方法即可。


3、实现

假设你在饭店点菜。

  • 你(Client 客户端):我要点“宫保鸡丁”。
  • 服务员(Invoker 调用者):拿到菜单,把点菜单(订单)交给厨房。
  • 订单(Command 命令对象):订单上写着“做宫保鸡丁”。
  • 厨师(Receiver 接收者):收到订单,立刻开始炒菜。

这样,服务员并不需要会做菜,他只要拿订单就行了。

3.1、没有命令模式

你直接告诉服务员 “去让张师傅做宫保鸡丁”:

代码如下所示:

// 直接耦合
public class Waiter {private Chef chef = new Chef();public void orderGongBaoChicken() {chef.makeGongBaoChicken();}
}public class Chef {public void makeGongBaoChicken() {System.out.println("炒宫保鸡丁!");}
}
// 调用
Waiter waiter = new Waiter();
waiter.orderGongBaoChicken();

3.2、命令模式写法

1. 命令接口

public interface Command {void execute();   // 执行命令void undo();      // 撤销命令(可选)
}
  • 这里的Command相当于“点菜单的模板”,所有的点菜单都要有一个execute方法。

2. 接收者(Receiver)——厨师

public class Chef {public void makeGongBaoChicken() {System.out.println("厨师:炒宫保鸡丁!");}public void makeFriedRice() {System.out.println("厨师:炒蛋炒饭!");}
}
  • Chef能够真的炒不同的菜。

3. 具体命令(ConcreteCommand)——不同的订单

public class GongBaoChickenCommand implements Command {private Chef chef;public GongBaoChickenCommand(Chef chef) {this.chef = chef;}@Overridepublic void execute() {chef.makeGongBaoChicken();}@Overridepublic void undo() {System.out.println("取消宫保鸡丁!");}
}public class FriedRiceCommand implements Command {private Chef chef;public FriedRiceCommand(Chef chef) {this.chef = chef;}@Overridepublic void execute() {chef.makeFriedRice();}@Overridepublic void undo() {System.out.println("取消蛋炒饭!");}
}
  • 每个命令就是一张“点菜单”,知道自己要交给哪个厨师(Receiver)。

4、调用者(Invoker)服务员

public class Waiter {private Command command;public void setCommand(Command command) {this.command = command;}public void placeOrder() {// 点菜command.execute();}public void cancelOrder() {// 撤销点菜command.undo();}
}

5、客户端组装

public class Customer {public static void main(String[] args) {Chef chef = new Chef();Command gongBaoChicken = new GongBaoChickenCommand(chef);Command friedRice = new FriedRiceCommand(chef);Waiter waiter = new Waiter();// 点宫保鸡丁waiter.setCommand(gongBaoChicken);waiter.placeOrder();// 点蛋炒饭waiter.setCommand(friedRice);waiter.placeOrder();// 撤销刚才的蛋炒饭waiter.cancelOrder();}
}

输出:

厨师:炒宫保鸡丁!
厨师:炒蛋炒饭!
取消蛋炒饭!

有上述示例可知命令模式的功能:

  • 解耦:Waiter只需要认识命令Command,不用知道Chef做什么。
  • 追加功能:要新增一道菜,只要做一个新的Command类即可,Waiter不用改。
  • 支持队列、日志、撤销:命令对象能被存储、排队,可以撤销。

4、命令模式的优缺点

1、优点:

彻底解耦“请求者”与“执行者”,调用者无需知道接收者是啥

请求可以参数化(每个对象带不同接收者和参数)。

请求可以放队列、做日志,如事务撤销与恢复、任务队列。

增加新命令类非常方便。

2、缺点:

类的数量可能会增多(每种命令都要实现 Command 接口)。


总结

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


参考文章:

1、设计模式第19讲——命令模式(Command)-CSDN博客文章浏览阅读1.1w次,点赞38次,收藏174次。命令模式是一种行为设计模式,它将请求封装为对象,使发出者和接收者解耦。文章介绍了命令模式的角色(抽象命令、具体命令、接收者和调用者),优缺点以及在餐厅点餐和Java场景中的应用,还提供了代码实现示例。 https://blog.csdn.net/weixin_45433817/article/details/131465270?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522d919eba72e6dd9b4ef68572ad0a68137%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=d919eba72e6dd9b4ef68572ad0a68137&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-131465270-null-null.142^v102^control&utm_term=%E5%91%BD%E4%BB%A4%E6%A8%A1%E5%BC%8F&spm=1018.2226.3001.4187

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

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

相关文章

【动态规划算法】路径问题

什么是动态规划算法动态规划(Dynamic Programming,简称 DP)是一种通过分解复杂问题为重叠子问题,并存储子问题的解以避免重复计算,从而高效求解具有特定性质(重叠子问题、最优子结构)问题的算法…

Java基本技术讲解

一、基础语法三要素 暂时无法在飞书文档外展示此内容 🔑 黄金法则​:每个变量都要声明类型!二、程序逻辑控制(游戏行为核心) 条件判断:if-else - “岔路口选择” // 捡到金币逻辑 if (isTouching(Coin.clas…

【网络基础2】路由器的 “两扇门”:二层接口和三层接口到底有啥不一样?

目录 前言:路由器不是只有 “插网线的口” 一、先搞懂一个基础:路由器是 “网络交通枢纽” 二、二层接口:“小区内部的单元门”,只认 “住户身份证” 1. 啥是二层接口? 2. 用 “小区内部串门” 理解二层接口 步骤 1:手机打包数据,写上 “收件人身份证” 步骤 2:二…

MLIR TableGen

简介 TableGen 是一种领域特定语言(DSL),TableGen 的设计目标是允许编写灵活的描述,并将记录的通用特性提取出来,从而减少重复代码并提高代码的可维护性。 TableGen的工作流程: 前端解析: Ta…

2、docker容器命令 | 信息查看

1、命令总览命令作用docker ps查看运行中的容器(-a查看所有容器)docker logs [CONTAINER]查看容器日志(-f实时追踪日志)docker inspect [CONTAINER]查看容器详细信息(JSON格式)docker stats [CONTAINER]实时…

【MySQL】MySQL中锁有哪些?

一、按照粒度分类: 粒度越小,并发度越高,锁开销越大。 1.全局锁: 作用: 锁定整个MySQL实例(所有数据库)。适用场景: 全库逻辑部分。(确保备份期间数据的一致性。)实现方式: 通过 FLUSH TABLES W…

语义分割--deeplabV3+

根据论文网络结构图讲一下:网络分为两部分:encoder和decoder部分。 Encoder:DCNN就是主干网络,例如resnet,Xception,MobileNet这些(主干网络也要使用空洞卷积),对dcnn的结…

Azure DevOps 中的代理

必知词汇 深入研究 Azure DevOps 中的代理之前需要掌握的基本概念: 代理:Azure DevOps 中的代理是一个软件组件,负责执行流水线中的任务和作业。这可能包括数据中心内的物理服务器、本地或云端托管的虚拟机,甚至是容器化环境。这些代理可以在各种操作系统和环境中运行,例如…

AUTOSAR进阶图解==>AUTOSAR_SRS_ADCDriver

AUTOSAR ADC驱动详解 基于AUTOSAR标准的ADC驱动模块需求规范分析目录 ADC驱动模块概述 关键概念定义 ADC驱动架构 ADC驱动在AUTOSAR分层架构中的位置ADC驱动的主要职责 ADC驱动配置结构 通用配置(AdcGeneral)硬件单元配置(AdcHwUnit)通道配置(AdcChannel)通道组配置(AdcChanne…

宝马集团与SAP联合打造生产物流数字化新标杆

在德国雷根斯堡的宝马工厂,每57秒就有一辆新车下线。这座工厂不仅是汽车制造的基地,更是宝马集团向SAP S/4HANA云平台转型的先锋项目。通过“RISE with SAP”计划,宝马将该工厂的运营系统全面迁移至SAP S/4HANA Cloud Private Edition&#x…

Go 语言实战:构建一个高性能的 MySQL + Redis 应用

引言:为什么是 Go MySQL Redis?在现代后端技术栈中,Go MySQL Redis 的组合堪称“黄金搭档”,被广泛应用于各种高并发业务场景。Go 语言:以其卓越的并发性能、简洁的语法和高效的执行效率,成为构建高性能…

Excel超级处理器,多个word表格模板中内容提取到Excel表格中

在职场中,很多人习惯在word里插入表格,设计模板,填写内容,一旦有多个word文件需要整理在excel表格中,最常见的工作方式就是每个word文件打开,复制,粘贴到excel表格里,这样的工作方式…

前端工程化:ES6特性

本文为个人学习笔记整理,仅供交流参考,非专业教学资料,内容请自行甄别 文章目录一、let与var1.1、越狱问题1.2、变量的重复声明1.3、变量提升问题二、解构2.1、数组解构2.2、对象解构2.3、方法解构三、链判断四、参数默认值五、箭头函数六、模…

大屏项目展示

一、项目克隆与基础操作 我们参考的项目 互联网设备可视化平台---IofTV-Screen: 🔥一个基于 vue、datav、Echart 框架的物联网可视化(大屏展示)模板,提供数据动态刷新渲染、屏幕适应、数据滚动配置,内部图表自由替换、Mixins注入等功能,持续更新.... 将次项目克隆到本…

基于R语言地理加权回归、主成份分析、判别分析等空间异质性数据分析实践技术应用

在自然和社会科学领域有大量与地理或空间有关的数据,这一类数据一般具有严重的空间异质性,而通常的统计学方法并不能处理空间异质性,因而对此类型的数据无能为力。以地理加权回归为基础的一系列方法:经典地理加权回归,…

【Flask 基础 ①】 | 路由、参数与模板渲染

0 序言 Flask 是 Python 生态中一款轻量级 Web 框架,以简洁、灵活著称。 学习 Flask 的意义在于: 快速开发:通过少量代码即可搭建功能完整的 Web 应用;理解原理:其设计清晰体现了 Web 框架的核心逻辑,如路由…

wordpress登陆前登陆后显示不同的顶部菜单

在WordPress中让“未登录”和“已登录”用户看到不同的顶部菜单,最干净、最安全、最可维护的做法是: 在同一个菜单位置(themelocation)里,根据is_user_logged_in()动态切换菜单。 下面给出三种常见实现方式,按推荐程度排序。任选…

【昇腾推理PaddleOCR】生产级部署方式

已知的在昇腾上推理Paddle OCR有三种方法: 概要: PyTorch官方提供了昇腾插件包,安装后虽然可以支持PytorchOCR和PaddlePaddle的推理任务,但性能较低。换句话说,PaddlePaddle框架层面支持了昇腾,但具体到某个…

LangChain摘要记忆组件的使用与解析

01. 摘要记忆组件的类型 在 LangChain 中使用缓冲记忆组件要不就保存所有信息(占用过多容量),要不就保留最近的记忆信息(丢失太多重要信息),那么有没有一种情况是既要又要呢? 所以折中方案就出…

NAT与智能选路

1、NAT 基础概念核心作用:私网地址无法在 Internet 上直接使用和分配,NAT 通过将私有地址与公有地址及端口进行转换,实现私网与公网的通信。转换示例:内网用户(10.1.1.1)访问外网 FTP Server(12…