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;}@Overridepublic void execute() {abcStock.buy();}
}public class SellStock implements Order {private Stock abcStock;public SellStock(Stock abcStock){this.abcStock = abcStock;}@Overridepublic 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

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

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

相关文章

flutter开发实战-设置bottomNavigationBar中间按钮悬浮效果

flutter开发实战-设置bottomNavigationBar中间按钮悬浮的效果 在使用tabbar时候&#xff0c;可以使用bottomNavigationBar来设置中间凸起的按钮&#xff0c;如下 一、效果图 中间按钮凸起的效果图如下 二、实现代码 我们使用BottomAppBar 一个容器&#xff0c;通常与[Sscaf…

2023年PMP证书的含金量有多高?对于企业来说有多大的价值?

PMP含金量更多的是“敲门砖”作用&#xff0c;公司招聘的门槛 当然现在PMP管理模式也很热门&#xff0c;各大企业都有引进改良应用在公司的项目上&#xff0c;之前在校友群里面大家在讨论PMP 的作用也有说到这一点&#xff0c;给大家看看吧。 至于为什么PMP认证从国外引进大陆…

⭐Unity 读取本地图片再区域裁剪

现在需求是将本地的图片读取之后再区域截图成新的图片 话不多说直接上代码 using UnityEngine; using System.IO;public class LocalRegionCapture : MonoBehaviour {public string fullScreenImagePath "Assets/SavedImages/fullScreenScreenshot.png";public str…

【PyQt学习篇 · ⑭】:QTableView的使用

文章目录 QTableView的使用示例 QTableView的使用 QTableView 是 PyQt 中用于显示表格数据的窗口部件&#xff0c;它提供了一个灵活的方式来显示和编辑数据。下面是一些关于 QTableView 的使用的具体信息&#xff1a; 创建 QTableView 对象&#xff1a; from PyQt5.QtWidgets …

python/C 生成beta分布的随机数

python/C 生成beta分布的随机数 文章目录 python/C 生成beta分布的随机数前言一、beta分布理论知识二、python 生成服从beta分布的随机数三、C语言生成服从beta分布的随机数 前言 想把一个算法用C语言实现&#xff0c;其中涉及到了beta分布取随机数&#xff0c;记录一下结果 一…

雀巢困在业绩和质量里

撰稿|行星 来源|贝多财经 雀巢集团CEO马克施奈德曾在2023年中报中表示&#xff0c;后疫情时代居家消费已恢复常态&#xff0c;从而消除了制约雀巢部分品类增长的阻碍。 但就雀巢前三季度财报而言&#xff0c;该公司在全球及大中华区的销售额均有所下降&#xff0c;有机增长主…

如何使用Java的GeoTools地理库计算WGS84坐标下的两个经纬度之间得距离

介绍 本章讲解如何使用Java的GeoTools地理库计算基于WGS84坐标的两点之间的距离。适用于后台服务的距离计算。 GeoTools介绍 GeoTools是开源的Java地理信息计算库。GeoServer地图引擎就是基于GeoTools库构建得地图服务,可以说非常强大。 官网地址:https://docs.geotools.o…

Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存(C#)

Baumer工业相机堡盟工业相机如何通过BGAPI SDK实现Raw格式的图像保存&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机通过SDK实现Raw格式的图像保存的技术背景通过SDK获取相机信息的代码分析Baumer工业相机回调函数里保存原始图像数据Baumer保存Raw图像格式重要核心代…

【JS】按照a>b>c>d>e>f的优先级,将a,b,c,d,e,f元素进行筛选,选出三个不为空字符的元素进行字符拼接

设计思路&#xff1a; 1、定义一个数组&#xff0c;把元素按照优先级进行排序&#xff1b; 2、 使用 filter() 方法过滤掉空字符串元素&#xff0c;得到一个新的数组; 3、在排序函数中&#xff0c;循环数组&#xff0c;使用 indexOf() 方法获取元素 a 和 b 在数组中的索引&a…

描述一个bug及定义bug的级别

&#xff08;一&#xff09;描述一个bug 描述一个bug&#xff0c;需要以下几个因素&#xff1a; 故障标题、故障发现的版本、故障类别&#xff08;功能/兼容/界面&#xff09;、故障优先级、故障描述&#xff08;测试环境、测试步骤、预期结果、实际结果&#xff09;。 举个例…

MySQL,使用Union组合查询

1、基本使用 Union可将多条select语句组合成一个结果集&#xff0c;常见的使用场景有2种&#xff1a; 在单个查询中&#xff0c;从不同的表返回类似结构的数据&#xff1b;对单个表执行多个查询&#xff0c;按单个查询返回数据。 例&#xff1a;检索出所有价格<50的产品&…

批发订货系统小程序怎么推广 四个方案高效获客

微信小程序基于强社交属性&#xff0c;天然自带引流特性&#xff0c;但毕竟小程序也只是一个工具&#xff0c;想要快速获客&#xff0c;还是需要商家主动采取一些措施的。下面分享是个方法&#xff0c;尤其是最后一个&#xff0c;是十分凑效的。大家点个关注点个赞&#xff0c;…

Android 权限申请

在Android中&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用在运行时需要动态申请权限。以下是一些步骤来动态申请权限&#xff1a; 在应用的清单文件&#xff08;AndroidManifest.xml&#xff09;中声明需要的权限。例如&#xff0c;如果应…

从零开发短视频电商 在AWS上用SageMaker部署自定义模型

文章目录 简介使用model.tar.gz1.从huggingface上下载模型2.自定义代码3.打包为tar 文件4.上传model.tar.gz到S35.部署推理 使用hub1.在sagemaker上新建个jupyterlab2.上传官方示例ipynb文件3.指定HF_MODEL_ID和HF_TASK进行部署和推理 inference.py官方示例 简介 原始链接&…

解决win10下强制设置web浏览器为microsoft edge的方法

目录 问题场景实现方法禁止edge默认选项设置默认浏览器 反思 问题场景 因为一些特殊的原因&#xff0c;我需要第二个浏览器&#xff0c;我的第一个浏览器是google的chrome浏览器&#xff0c;所以我选择的是windows的默认浏览器&#xff0c;就是microsoft edge浏览器&#xff0…

【Java】Mybatis

MyBatis JavaEE三层框架&#xff1a;表现层、业务层、持久层。 现在开始学习持久层。持久层就是负责与数据库打交道的代码。 框架&#xff1a;就是一个半成品软件。在框架的基础上&#xff0c;可以更加高效地写出代码。 1、MyBatis快速入门 1、准备工作&#xff08;创建sp…

【大模型】快速体验百度智能云千帆AppBuilder搭建知识库与小助手

文章目录 前言千帆AppBuilder什么是千帆AppBuilderAppBuilder能做什么 体验千帆AppBuilderJava知识库高考作文小助手 总结 前言 前天&#xff0c;在【百度智能云智算大会】上&#xff0c;百度智能云千帆AppBuilder正式开放服务。这是一个AI原生应用开发工作台&#xff0c;可以…

【C++入门到精通】互斥锁 (Mutex) C++11 [ C++入门 ]

阅读导航 引言一、Mutex的简介二、Mutex的种类1. std::mutex &#xff08;基本互斥锁&#xff09;2. std::recursive_mutex &#xff08;递归互斥锁&#xff09;3. std::timed_mutex &#xff08;限时等待互斥锁&#xff09;4. std::recursive_timed_mutex &#xff08;限时等待…

【沁恒蓝牙mesh】CH58x DataFlash 详解

本文主要介绍了 沁恒蓝牙芯片 CH58x 的 DataFlash 分区以及读写操作以及原理 &#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是喜欢记录零碎知识点的小菜鸟。&#x1f60e;&#x1f4dd; 个人主页&#xff1a;欢迎访问我的 Ethernet_Comm 博…

CUMT--Java复习--JDBC编程

目录 一、JDBC简介 二、数据库访问 1、加载数据库驱动 2、建立数据连接 3、创建Statement对象 4、执行SQL语句 5、访问结果集 三、MetaData接口 1、DatabaseMetaData接口 2、ResultSetMetaData接口 四、事务 1、JDBC中的事务 2、保存点 3、批量更新 一、JDBC简…