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

行为设计模式 -命令模式- JAVA

命令模式

    • 一.简介
    • 二. 案例
      • 2.1 接收者(Receiver)
      • 2.2 命令接口实现对象(ConcreteCommand)
      • 2.3 调用者( invoker)
      • 2.4 获取Receiver对象
      • 2. 5 装配者客户端测试
    • 三. 结论
      • 3.1 要点
      • 3.2 示例

前言
本设计模式专栏写了很多设计模式的文章,希望大家点赞收藏一起学习
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一.简介

百度百科: 在软件系统中,行为请求者行为实现者通常呈现一种紧耦合。但在某些场合,比如要对行为进行记录、撤销/重做、事务等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将行为请求者与行为实现者解耦?将一组行为抽象为对象实现二者之间的松耦合。这就是命令模式(Command Pattern)。

个人理解: 某个行为有多个对象执行,并且我们需要对这个行为进行一些监控等处理。那么我们就需要将这种行为抽象出来,这种就叫做命令模式

在命令模式中有如下角色:

  • 接收者(Receiver): 任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
  • 命令接口实现对象(ConcreteCommand): 是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • 调用者(Invoker): 要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
  • 装配者(Client): 创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者。

接下来使用示例和代码来加深理解

二. 案例

举个例子:

  1. 场景:有两个人听从教练的指挥互相传球,一个用左手传,一个用右手传。
  2. 结论: 可以看出,我们有两个对象,简称为左手人和右手人,他们有一个共同的行为就是传球。由谁进行传球这个行为是教练下的命令。这时候就可以使用命令模式

类图如下

image-20240913104404498

2.1 接收者(Receiver)

我们首先定义两个人物对象

定义接收者的接口

/*** @Author chenyunzhi* @DATE 2024/9/12 15:13* @Description: 接收者*/
public interface BallReceiver {void passBall();
}

使用左手投球的人

/*** @Author chenyunzhi* @DATE 2024/9/12 15:14* @Description: 使用左手接收者*/
public class LeftHandPeopleReceiver implements BallReceiver{@Overridepublic void passBall() {System.out.println("人物1使用左手传球");}
}

使用右手投球的人

/*** @Author chenyunzhi* @DATE 2024/9/12 15:16* @Description: 使用右手接收者*/
public class RightHandPeopleReceiver implements BallReceiver{@Overridepublic void passBall() {System.out.println("人物2使用右手传球");}
}

2.2 命令接口实现对象(ConcreteCommand)

接下来我们要将传球这个命令抽象出来

定义执行命令的接口

/*** @Author chenyunzhi* @DATE 2024/9/12 15:19* @Description: 执行命令*/
public interface Command {void execute();
}

定义传球命令

/*** @Author chenyunzhi* @DATE 2024/9/12 15:23* @Description: 传球命令*/
public class PassBallCommand implements Command{private final BallReceiver ballReceiver;public PassBallCommand(BallReceiver ballReceiver) {this.ballReceiver = ballReceiver;}@Overridepublic void execute() {this.ballReceiver.passBall();}
}

现在我们已经准备好了接收者和命令实现,因此我们可以开始实现 调用者( invoker) 类。

2.3 调用者( invoker)

调用者的任务就是负责调用具体的命令

/*** @Author chenyunzhi* @DATE 2024/9/12 16:27* @Description: 命令的调度者,执行命令*/
public class BallInvoker {public Command command;public BallInvoker(Command command) {this.command = command;}public void execute() {this.command.execute();}
}

2.4 获取Receiver对象

命令模式已经准备就绪,我们可以开始编写一个简单的命令模式客户端程序。但在此之前,我将提供一个方法来创建相应的 BallReceiver 对象。我们可以通过工厂+策略模式去获取对应的人物对象

/*** @Author chenyunzhi* @DATE 2024/9/12 16:36* @Description: 使用工厂模式设计*/
public class PeopleReceiverFactory {public static BallReceiver getBallReceiver(String people) {switch (people) {case "LEFT_HAND":return new LeftHandPeopleReceiver();case "RIGHT_HAND":return new RightHandPeopleReceiver();default:return null;}}
}

如果命令很多,比如这里不止传球,还有打球,投球等等,这些行为可以通过工厂的方式获取。

2. 5 装配者客户端测试

准备工作已经完成,那么我们接下来就也可以开始测试了

/*** @Author chenyunzhi* @DATE 2024/9/12 16:45* @Description:*/
public class CommandPatternClient {/*** 装配者*/public static void ballClient(String receiver) {// 创建左手传球的接收者对象BallReceiver ballReceiver = PeopleReceiverFactory.getBallReceiver(receiver);// 创建命令并与接收者关联PassBallCommand passBallCommand = new PassBallCommand(ballReceiver);// 创建调用者与命令关联BallInvoker ballInvoker = new BallInvoker(passBallCommand);// 对调用者对象执行命令ballInvoker.execute();}public static void main(String[] args) {ballClient("LEFT_HAND");ballClient("RIGHT_HAND");}
}

ballClient方法负责组装命令对象和接收者。最后输出结果

image-20240913103844539

三. 结论

3.1 要点

  • 接收器实现与命令实现是分开的。
  • 命令实现类选择要在接收器对象上调用的方法,接收器中的每个方法都将有一个命令实现。它充当接收者和操作方法之间的桥梁。
  • Invoker 类只是将请求从 client 转发到 command 对象。
  • 客户端负责实例化适当的命令和接收器实现,然后将它们关联在一起。
  • Client 还负责实例化 invoker 对象并将 command object 与其关联,并执行 action 方法。
  • 命令设计模式很容易扩展,我们可以在接收器中添加新的动作方法,并在不改变客户端代码的情况下创建新的命令实现。
  • Command 设计模式的缺点是,由于有太多的关联,代码会变得庞大且令人困惑。

3.2 示例

java.lang.Runnable

javax.swing.Action

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。

相关文章:

行为设计模式 -命令模式- JAVA

命令模式 一.简介二. 案例2.1 接收者(Receiver)2.2 命令接口实现对象(ConcreteCommand)2.3 调用者( invoker)2.4 获取Receiver对象2. 5 装配者客户端测试 三. 结论3.1 要点3.2 示例 前言 本设计模式专栏写了…...

使用redis实现发布订阅功能及问题

如何使用redis实现发布订阅及遇到的问题 使用背景: 服务A通过接口操作服务B,实现相应逻辑。生产环境上,服务A有两个pod,服务B有3个pod 通过接口调用时,请求只能打到服务B的一个pod上,而我们想要的是服务B的…...

Debug日程工作经验总结日程常用

数据库 db连接命令 kubectl exec -it -n de dbs-53-cdf57d8dd-l4l29 sh su - postgres psql psql -h 10.115.19.118 -p 12080 -U postgres -d clouddb SET search_path TO “h.com”; select * from ems_ice limit 1; 也可以不切换schema,直接sql查询 select * f…...

Apache Paimon主键表的一些最佳实践

今天我们说说Paimon主键表的一些使用上的注意事项。 一、主键表 主键表是Paimon的一种表类型。用户可以插入、更新或删除表中的记录。 说的直白点就是,允许你设置唯一主键,然后覆盖更新。 Bucket选择 无论分区表还是未分区表,Bucket都是最小的…...

React面试常见题目(基础-进阶)

React面试常见题目及详细回答讲解 基础题目(20个) 什么是React? 回答:React是一个用于构建用户界面的JavaScript库,它允许你将UI拆分成可复用的组件。React起源于Facebook的内部项目,用于构建高性能的Web应…...

AI赋能:开启你的副业创业之路

随着人工智能(AI)技术的迅猛发展,越来越多的人开始探索与之相关的副业机会。AI不仅深刻改变了我们的工作和生活方式,还为愿意学习和运用这项技术的人们打开了丰富的创业和增收之门。今天,我们就来盘点几条与AI相关的副…...

前端文件上传组件流程的封装

1. 前端文件上传流程 选择文件&#xff1a; 用户点击上传按钮&#xff0c;选择要上传的文件。使用 <input type"file"> 或 FileReader API 读取文件。 文件校验&#xff1a; 校验文件的大小、格式等信息&#xff0c;提前过滤掉不符合要求的文件&#xff0c;避免…...

图像篡改研究

使用生成对抗网络 (GAN) 来篡改已有的图片涉及生成和修改图像的技术。以下是如何使用GAN对现有图像进行篡改的详细步骤&#xff1a; 1. 选择合适的GAN模型 不同类型的GAN模型适用于不同的图像处理任务。以下是几个常见的GAN模型及其应用&#xff1a; CycleGAN&#xff1a;用…...

wlan的8种组网方式的区别

1&#xff09;方式一&#xff1a;直连模式 二层组网&#xff08;直接转发/ 集中转发&#xff09; &#xff08;2&#xff09;方式二&#xff1a;直连模式 三层组网&#xff08;集中转发&#xff09; &#xff08;3&#xff09;方式三&#xff1a;旁挂模式 二层组网&#xff08;…...

取消element-ui中账号和密码登录功能浏览器默认的填充色,element-ui登录账号密码输入框禁用浏览器默认填充色问题

标题 问题展示 修改后 <div class="loginForm"><el-formref="formB":model="formDataB":rules="rulesB"class="login-form"label-position="left"><el-form-item prop="userNo" clas…...

Postman:高效的API测试工具

在现代软件开发中&#xff0c;前后端分离的架构越来越普遍。前端开发者与后端开发者之间的协作需要一种高效的方式来测试和验证API接口。在这个背景下&#xff0c;Postman作为一款强大的API测试工具&#xff0c;受到了广泛的关注和使用。 今天将介绍什么是Postman、为什么要使用…...

设计模式-观察者模式(代码实现、源码级别应用、使用场景)

提示&#xff1a;观察者模式的代码实现、观察者模式的使用场景、观察者模式源码级别的应用、观察者模式的优点、 文章目录 前言一、定义二、类图三、代码实现四、应用场景五、源码级别的应用总结 前言 随着时间的推移&#xff0c;我现在越来越感觉自己的代码不够优雅了&#x…...

9种 Vuejs 常用事件修饰符与使用指南

前言 事件修饰符是 Vue.js 中一种特殊的语法标记&#xff0c;通过在事件名称后加上 . 和修饰符名称&#xff0c;可以轻松地修改事件的默认行为。这些修饰符不仅能够提升代码的清晰度&#xff0c;还能够避免一些常见的编程陷阱。Vue.js 提供了一系列事件修饰符&#xff0c;帮助…...

第十四题刮开有奖

这道题还是将我们下载好的附件先查壳 发现无壳且为32位 所以我们用32位的IDA打开 打开后ShftF12发现一串可疑的字符串 我们跟进看看 发现了这个函数 看这里有string数组 首先给了一串七v7 v8v9的数据 下面还有一个函数 我们再跟进一下 发现这大概是前面v7那堆数据的加密方式 我…...

vue3+vite使用dataV后项目运行报错、页面空白问题

Vue 大屏数据展示组件库官网&#xff1a;http://datav.jiaminghi.com/guide/ 我的版本是&#xff1a;“jiaminghi/data-view”: “^2.10.0” 一、dataV引入&#xff0c;看官网也可 // 安装 &#xff08; 我的安装版本 "jiaminghi/data-view": "^2.10.0" …...

PDF 【人工智能白皮书 】【大模型安全实践白皮书】【大模型白皮书】【大模型/深度学习/人工智能原理/心智学习】

【2024 中国人工智能发展白皮书 】【2023 中国人工智能白皮书】【大模型/深度学习/人工智能原理/心智学习】 前言下面所有涉及到的白皮书文件的总下载链接&#xff08;网盘&#xff09;&#xff1a; 2024 人工智能发展白皮书 深圳市易行网数字科技有限公司2024 大模型训练数据白…...

【vue】13.深入理解递归组件

在Vue.js的开发实践中&#xff0c;组件是构建界面的核心概念。而递归组件则是一种特殊的组件&#xff0c;它能够自己调用自己&#xff0c;从而创造出无限嵌套的界面结构。本文将带你了解递归组件的应用&#xff0c;以及如何在Vue中实现和使用它。 一.什么是递归组件&#xff1f…...

【OFDM】OFDM Radar Algorithms in Mobile Communication Networks

[1] Maximum Likelihood Speed and Distance Estimation for OFDM Radar 1-CRB估计 1-初步形式 首先单频信号频率估计的CRB,也就是原文Eq.(3.53) v a r [ ω ^ ] ≥ 6 σ N 2 ( N 2 − 1 ) N \mathrm{var}[\hat{\omega}]\geq\frac{6\sigma_N^2}{(N^2-1)N} var[ω^]≥(N2−…...

如何检测java中的内存泄露及溢出,并预防?

引言 在Java开发中,内存管理是一个至关重要的方面。尽管Java有垃圾回收机制,但开发者仍然需要关注内存泄漏和溢出的问题。 内存泄漏会导致应用程序的性能下降,甚至崩溃,而内存溢出则会导致Java虚拟机(JVM)抛出OutOfMemoryError异常。 本文将探讨如何检测Java项目中的内…...

kafka 如何减少数据丢失?

大家好&#xff0c;我是锋哥。今天分享关于【kafka 如何减少数据丢失?】面试题&#xff1f;希望对大家有帮助&#xff1b; kafka 如何减少数据丢失? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Apache Kafka 是一个高吞吐量的分布式消息队列&#xff0c;广泛用…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

华为OD机考-机房布局

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...