java设计模式学习之【命令模式】

文章目录

  • 引言
  • 命令模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 在Spring框架中的应用
  • 股票示例
  • 代码地址

引言

想象一下,你在一个忙碌的厨房里,厨师们正忙于准备各种菜肴。每当服务员带来一个新订单时,他们不会直接对厨师说需要做什么菜。相反,订单被写在纸上,并放置在一个订单队列中。厨师们会一个接一个地取订单,并准备相应的菜肴。这里,每个订单就像是一个“命令”,它包含了需要执行的所有信息。在软件开发中,我们处理命令时也可以采取类似的方式。命令模式允许我们以同样的方式封装所有信息,这些信息需要执行某项操作或触发某个事件,然后像传递订单一样传递这些命令。

命令模式简介

定义与用途

命令模式(Command Pattern)是一种行为型设计模式,它将一个请求或简单操作封装为一个对象。这种模式允许用户根据不同的请求将方法调用、请求或操作封装到单独的对象中,并将这些对象传递给调用者。调用者随后可以根据需求执行这些操作。这种模式通常用于:队列操作、回调操作和对请求的日志记录。

实现方式

实现命令模式涉及以下几个关键组件:

  • 命令接口(Command):定义了执行操作的接口。
  • 具体命令(Concrete Command):实现命令接口,定义接收者上执行的动作。
  • 接收者(Receiver):执行与请求相关联的操作。
  • 调用者(Invoker):持有命令,并在某个时间点调用命令的执行方法。
  • 客户端(Client):创建具体命令,并设置其接收者。

使用场景

命令模式适用于以下场景:
当需要将请求发送者和请求接收者解耦时。
当需要对请求的排队、记录或可撤销操作时。
在需要支持宏命令和事务系统的场景中。

例如:

  1. GUI按钮和菜单项:GUI的按钮和菜单项通常使用命令模式来处理用户输入。
  2. 事务型行为:命令模式可以用来实现事务系统,其中命令有执行和回滚两种操作。
  3. 多级撤销功能:在支持撤销操作的系统中,命令模式可以用来记录操作的历史,以便用户可以撤销或重做它们。

优势与劣势

  • 优势
    降低系统的耦合度:命令模式将调用操作的对象与知道如何实施该操作的对象解耦。
    增强了扩展性:可以很容易地增加新的命令。
    可以组合命令:可以组合多个命令,实现复杂的功能。
  • 劣势
    可能会导致某些系统有过多的具体命令类。

在Spring框架中的应用

JdbcTemplate 是Spring框架中使用命令模式的一个很好的例子。在JdbcTemplate的上下文中,命令模式提供了一种强大的机制来抽象和封装对数据库的各种操作。它允许JdbcTemplate通过执行各种StatementCallback实现来灵活地执行各种操作,同时保持其自身的简洁和不涉及具体数据库操作的逻辑。

(1)命令接口(Command)- StatementCallback
StatementCallback<T>接口 在这个上下文中类似于命令模式中的命令接口。它定义了一个doInStatement(Statement stmt)方法,该方法接收一个Statement对象作为参数。不同的实现将对数据库执行不同的操作。
(2)具体命令和接收者 - QueryStatementCallBack和其他实现
具体命令 由实现StatementCallback接口的类表示,例如QueryStatementCallBack。这些类封装了对数据库执行特定操作的逻辑。
同时充当命令接收者:在这种情况下,具体命令类(例如QueryStatementCallBack)不仅表示命令,还包含执行命令所需的逻辑,因此它们也扮演了接收者的角色。它们知道如何操作数据库来执行特定的操作。
(3)命令调用者 - JdbcTemplate
JdbcTemplate 是命令调用者。它提供了一个execute方法,该方法接受一个StatementCallback对象。JdbcTemplate不关心StatementCallback的具体操作,它只调用doInStatement方法并传递必要的Statement对象。这样,JdbcTemplate就可以执行各种不同的数据库操作,而不需要知道具体的细节。
(4)不同的具体命令实现
StatementCallback的其他实现,如QueryStatementCallback,为不同类型的数据库操作提供了具体实现。每个实现都有自己独特的doInStatement方法,它们封装了如何使用传递给它们的Statement来执行操作。

股票示例

在这里插入图片描述
步骤 1:创建命令接口
首先定义了一个 Order 接口,作为命令的角色。

public interface Order {
   void execute();
}

这个接口定义了一个execute方法,所有的命令都将实现这个方法来执行它们的操作。

步骤 2:创建请求类
创建了一个 Stock 类,作为请求的角色。

public class Stock {
	
   private String name = "ABC";
   private int quantity = 10;

   public void buy(){
      System.out.println("股票 [ 名称: "+name+", 数量: " + quantity +" ] 购买了");
   }
   public void sell(){
      System.out.println("股票 [ 名称: "+name+", 数量: " + quantity +" ] 卖出了");
   }
}

这个类代表一个股票,有买入和卖出的操作。

步骤 3:创建具体命令类
创建了实现Order接口的具体命令类。

public class BuyStock implements Order {
   private Stock abcStock;

   public BuyStock(Stock abcStock){
      this.abcStock = abcStock;
   }

   @Override
   public void execute() {
      abcStock.buy();
   }
}

public class SellStock implements Order {
   private Stock abcStock;

   public SellStock(Stock abcStock){
      this.abcStock = abcStock;
   }
	
   @Override
   public void execute() {
      abcStock.sell();
   }
}

BuyStock和SellStock是具体的命令,分别代表购买股票和出售股票的操作。

步骤 4:创建命令调用者类
创建了一个 Broker 类,作为命令的调用者。

import java.util.ArrayList;
import java.util.List;

public class Broker {
   private List<Order> orderList = new ArrayList<Order>(); 

   public void takeOrder(Order order){
      orderList.add(order);		
   }

   public void placeOrders(){
      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}

Broker 可以接受和存储命令,然后一次性执行这些命令。它通过调用每个命令的execute方法来执行命令。

步骤 5:使用 Broker 类来接受和执行命令

public class CommandPatternDemo {
   public static void main(String[] args) {
      Stock abcStock = new Stock();

      BuyStock buyStockOrder = new BuyStock(abcStock);
      SellStock sellStockOrder = new SellStock(abcStock);

      Broker broker = new Broker();
      broker.takeOrder(buyStockOrder);
      broker.takeOrder(sellStockOrder);

      broker.placeOrders();
   }
}

在这里插入图片描述
在这个客户端中,我们创建了买入和卖出股票的命令,然后通过Broker来执行它们。这个例子演示了命令模式如何用于参数化对象以及如何将请求排队等待执行。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch Reroute API 的使用

本文通过一个 Elasticsearch 集群中主分片分配不均衡的例子演示一下 Cluster reroute API 的使用。 对于 Elasticsearch 分片分配策略不了解的同学可以点一下关注&#xff0c;后面更文之后获取第一手资料。 环境信息 Windows 10 Elasticsearch 8.1 JDK17 初始集群状态 分片…

在Jetpack Compose中使用ExoPlayer进行直播流和音频均衡器

在Jetpack Compose中使用ExoPlayer进行直播流和音频均衡器 背景 ExoPlayer与Media3的能力结合&#xff0c;为Android应用程序播放多媒体内容提供了强大的解决方案。在本教程中&#xff0c;我们将介绍如何设置带有Media3的ExoPlayer来支持使用M3U8 URL进行直播流。此外&#x…

17个常用经典数据可视化图表与冷门图表

数据可视化是创建信息图形表示的过程。随着可视化技术的飞速发展&#xff0c;可以利用强大的可视化工具选择合适的数据可视化图表来展示数据。以下专业人士都应该知道的一些最重要的数据可视化图表。 常见数据可视化图表 饼图 饼图是最常见和最基本的数据可视化图表之一。饼图…

C++ 复合数据类型:指针

文章目录 指针用法无效指针空指针void *ptr指向指针的指针指向常量的指针指针常量指针和数组指针数组和数组指针 指针 计算机中的数据都存在内存中&#xff0c;访问内存的最小单元是“字节”&#xff0c;所有数据&#xff0c;就保存在内存中具有连续编号的一串字节中。 指针顾…

python三大开发框架django、 flask 和 fastapi 对比

本文讲述了什么启发了 FastAPI 的诞生&#xff0c;它与其他替代框架的对比&#xff0c;以及从中汲取的经验。 如果不是基于前人的成果&#xff0c;FastAPI 将不会存在。在 FastAPI 之前&#xff0c;前人已经创建了许多工具 。 几年来&#xff0c;我一直在避免创建新框架。首先&…

竞赛保研 基于LSTM的天气预测 - 时间序列预测

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 机器学习大数据分析项目 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/po…

Python深度学习029:pytorch中常用的模块或方法

PyTorch是一个广泛使用的深度学习库,提供了许多用于构建和训练神经网络的模块和方法。下面是一些PyTorch中常用的模块和方法的简要介绍: PyTorch常用模块和方法 torch 用途:PyTorch的基础模块,提供了多种数学运算功能。常用方法: torch.tensor():创建张量torch.randn():…

使用for语句换行打印久久乘法表格

一、基本思想 思想来源于九九乘法表&#xff0c;使用*来表示乘法并进行乘法的运算&#xff0c;最大的思想就是双层for循环&#xff0c;最关键的思想是进行里面的第二次for循环时&#xff0c;第二次索引的变量要小于等于第一次索引的变量。 二、 相关代码 public class Jiujiu…

IntelliJ IDEA 2023.3 安装教程

引言 IntelliJ IDEA&#xff0c;通常简称为 IDEA&#xff0c;是由 JetBrains 开发的一款强大的集成开发环境&#xff0c;专为提升开发者的生产力而设计。它支持多种编程语言&#xff0c;包括 Java、Kotlin、Scala 和其他 JVM 语言&#xff0c;同时也为前端开发和移动应用开发提…

实战:使用 OpenCV 和 PyTesseract 对文档进行 OCR

随着世界各地的组织都希望将其运营数字化&#xff0c;将物理文档转换为数字格式是非常常见的。这通常通过光学字符识别 (OCR) 完成&#xff0c;其中文本图像&#xff08;扫描的物理文档&#xff09;通过几种成熟的文本识别算法之一转换为机器文本。当在干净的背景下处理打印文本…

BUUCTF-Crypto合集-WP

获取CTF工具可关注CSJH网络安全团队&#xff0c;回复CTF工具 一眼就解密 下面的字符串解密后便能获得flag&#xff1a;ZmxhZ3tUSEVfRkxBR19PRl9USElTX1NUUklOR30 注意&#xff1a;得到的 flag 请包上 flag{} 提交 大小写字母加数字&#xff0c;而且等于号结尾&#xff0c;bas…

最新技术整理3款开源免费直播推流工具,实现实时视频推流、视频拉流,目标端可以是服务器、云平台、移动设备等(附源码)

最新技术整理3款开源免费直播推流工具&#xff0c;实现实时视频推流、视频拉流&#xff0c;目标端可以是服务器、云平台、移动设备等&#xff08;附源码&#xff09;。 什么是推流&#xff1f; 视频推流是指将实时的视频数据从一个源端发送到一个或多个目标端的过程。推流的源…

HTTP前端请求

目录 HTTP 请求1.请求组成2.请求方式与数据格式get 请求示例post 请求示例json 请求示例multipart 请求示例数据格式小结 3.表单3.1.作用与语法3.2.常见的表单项 4.session 原理5.jwt 原理 HTTP 请求 1.请求组成 请求由三部分组成 请求行请求头请求体 可以用 telnet 程序测…

基于Java+Swing实现大鱼吃小鱼小游戏(含用户登陆、注册功能)

基于JavaSwing实现大鱼吃小鱼小游戏 一、系统实现二、功能展示1.效果演示2.游戏界面3.游戏运行界面4.用户登陆 三、其他系统四源码下载 一、系统实现 1、创建窗口对象Ui 2、背景的绘制 3、键盘的监听事件 4、将己方鱼放上去 5、让小鱼移动 6、其他的鱼并引导&#xff08;先创建…

MFC使用高速绘图控件high-speed Charting Control绘制柱形图

1. 创建MFC单文档工程BarChartDemo。 2. 在工程文件夹下新建文件夹ChartCtrl,将ChartCtrl源码放入,如下图所示。在工程中添加这些项,项目——添加——现有项,全部添加。 3. 添加一个对话框,ID为IDD_DLG_BAR,类名为CBarDlg。 4. 在对话框中添加Custom Control控件,将控…

Dynamic Coarse-to-Fine Learning for Oriented Tiny Object Detection(CVPR2023待补)

文章目录 BeginningAbstract挑战方法成果 Introduction引出问题早期的work及存在的问题近期的work及存在的问题our workContribution Related Work&#xff08;paper for me&#xff09;Oriented Object DetectionPrior for Oriented ObjectsLabel Assignment Tiny Object Dete…

鸿蒙开发者工具安装及入门程序

下载工具DevEco Studio IDE 官网下载&#xff1a;HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 开发工具的安装 解压下载好的压缩包&#xff0c;一路无脑安装即可&#xff0c;安装完的使用方法类似于IDEA、WebStorm的使用&#xff0c;快捷键一致&#xff0c;默认黑…

【顶级快刊】IEEE(Trans),审稿快仅2个月录用,入选CCF-B,现在投最快!

计算机类 • 好刊解读 今天小编带来IEEE旗下计算机领域顶刊&#xff0c;顶级快刊&#xff0c;CCF-B类推荐&#xff0c;如您有投稿需求&#xff0c;可作为重点关注&#xff01;后文有相关领域真实发表案例&#xff0c;供您投稿参考~ 01 期刊简介 IEEE Transactions on Affect…

C++结合OpenCV:掌握图像基础与处理

本文详细介绍了使用 OpenCV4 进行图像处理的基础知识和操作。内容包括图像的基础概念、色彩空间理解、以及如何在 C 中进行图像读取、显示和基础操作。 1.图像的基本概念与术语 图像表示 在计算机视觉中&#xff0c;图像通常表示为一个二维或三维的数组。二维数组表示灰度图像&…

数据分析基础之《numpy(5)—合并与分割》

了解即可&#xff0c;用panads 一、作用 实现数据的切分和合并&#xff0c;将数据进行切分合并处理 二、合并 1、numpy.hstack 水平拼接 # hstack 水平拼接 a np.array((1,2,3)) b np.array((2,3,4)) np.hstack((a, b))a np.array([[1], [2], [3]]) b np.array([[2], […