Java特性之设计模式【命令模式】

一、命令模式

概述

​ 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令

​ 将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化

主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适

何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合

优缺点

优点:

  • 降低了系统耦合度
  • 新的命令可以很容易添加到系统中去

缺点:

  • 使用命令模式可能会导致某些系统有过多的具体命令类

1. 各个角色介绍

1.1 命令(Command)

  • 定义了执行操作的接口,通常包含一个 execute 方法,用于调用具体的操作

1.2 具体命令(ConcreteCommand)

  • 实现了命令接口,负责执行具体的操作。它通常包含了对接收者的引用,通过调用接收者的方法来完成请求的处理

1.3 接收者(Receiver)

  • 知道如何执行与请求相关的操作,实际执行命令的对象

1.4 调用者/请求者(Invoker)

  • 发送命令的对象,它包含了一个命令对象并能触发命令的执行。调用者并不直接处理请求,而是通过将请求传递给命令对象来实现

1.5 客户端(Client)

  • 创建具体命令对象并设置其接收者,将命令对象交给调用者执行

2. UML图

​ 首先创建作为命令的接口 Instruction,然后创建作为请求的 Activity 类。实体命令类 BuyActivitySellActivity,实现了 Instruction 接口,将执行实际的命令处理。创建作为调用对象的类 BrokerInvoker,它接受订单并能下订单

BrokerInvoker 对象使用命令模式,基于命令的类型确定哪个对象执行哪个命令。CommandPatternDemo 类使用 BrokerInvoker 类来演示命令模式

在这里插入图片描述

3. 具体例子和代码

角色分配

  • Instruction:命令 / 指令
    • BuyActivity:购买动作(实现命令接口)
    • SellActivity:销售动作(实现命令接口)
  • Activity:执行动作
  • BrokerInvoker:调用者

3.1 命令 / 指令接口以及实现类

  • Instruction
package com.vinjcent.prototype.command;/*** @author vinjcent* @description 命令*/
public interface Instruction {/*** 需要执行的命令*/void execute();}
  • BuyActivity
package com.vinjcent.prototype.command;/*** @author vinjcent* @description 购买动作*/
public class BuyActivity implements Instruction {/*** 动作*/private Activity activity;public BuyActivity(Activity activity) {this.activity = activity;}public Activity getActivity() {return activity;}public void setActivity(Activity activity) {this.activity = activity;}@Overridepublic void execute() {activity.buy();}}
  • SellActivity
package com.vinjcent.prototype.command;/*** @author vinjcent* @description 销售动作*/
public class SellActivity implements Instruction {/*** 动作*/private Activity activity;public SellActivity(Activity activity) {this.activity = activity;}public Activity getActivity() {return activity;}public void setActivity(Activity activity) {this.activity = activity;}@Overridepublic void execute() {activity.sell();}}

3.2 执行动作类

  • Activity
package com.vinjcent.prototype.command;/*** @author vinjcent* @description 执行动作*/
public class Activity {/*** 操作名称*/private String operationName;public String getOperationName() {return operationName;}public void setOperationName(String operationName) {this.operationName = operationName;}public void buy() {System.out.println("Instruction [ Operation: " + operationName + " bought ]");}public void sell() {System.out.println("Instruction [ Operation: " + operationName + " sold ]");}}

3.3 调用者类

  • BrokerInvoker
package com.vinjcent.prototype.command;import com.vinjcent.api.utils.CollectionUtils;import java.util.ArrayList;
import java.util.List;/*** @author vinjcent* @description 调用者*/
public class BrokerInvoker {/*** 调用者需要执行命令*/private List<Instruction> instructions;/*** 将命令加入调用者** @param instruction 加入的命令*/public void then(Instruction instruction) {if (CollectionUtils.isEmpty(instructions)) {instructions = new ArrayList<>();}instructions.add(instruction);}/*** 调用者执行命令*/public void run() {for (Instruction instruction : instructions) {instruction.execute();}instructions.clear();}}

3.4 测试主函数

package com.vinjcent.prototype.command;/*** @author vinjcent*/
public class Main {public static void main(String[] args) {// 构造动作Activity activity = new Activity();activity.setOperationName("order");BuyActivity buyInstruction = new BuyActivity(activity);SellActivity sellInstruction = new SellActivity(activity);// 构造调用者BrokerInvoker broker = new BrokerInvoker();// 为调用者添加购买、销售指令broker.then(buyInstruction);broker.then(sellInstruction);// 执行指令broker.run();}}
  • 测试结果

在这里插入图片描述

4. 使用场景

  • 认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令; 2、模拟 CMD

注意事项:

系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式

在这里插入图片描述

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

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

相关文章

springcloud -服务注册治理之nacos

任务 查询&#xff1a; CPU密集型和IO密集型对 CPU内核之间的关系。—线程池 什么是Nacos **服务&#xff08;Service&#xff09;**是 Nacos 世界的一等公民。Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理&#xff1a; Kubernetes Service gRPC & Dubbo RPC S…

打卡今天内存管理

首先我们的体系结构是这样的&#xff0c;根据小林coding 来写的笔记 寄存器&#xff0c;速度非常快&#xff0c; 32位的可以存4个字节&#xff0c;64位的可以存8个字节 多少位只是在32位以上 地址空间 分为两种地址空间 &#xff1a; 物理&#xff0c;逻辑 地址空间 地址空间…

【文献管理】zotero插件4——获取知网pdf、中文文献识别与目录生成

文章目录 zotero获取知网PDFzotero——中文文献识别&#xff08;茉莉花插件&#xff09;学位论文目录生成 zotero获取知网PDF zotero——中文文献识别&#xff08;茉莉花插件&#xff09; 为下载的学位论文添加目录中文文献识别&#xff1a;jasminum 下载pdflabs下载茉莉花插…

百度翻译相关介绍

官网地址&#xff1a;百度翻译(baidu.com) 通用文本翻译API 通用翻译API是百度翻译依托领先的自然语言处理技术推出的在线文本翻译服务&#xff0c;可支持中、英、日、韩等200语言互译&#xff0c;100语种自动检测。 传入待翻译内容&#xff0c;并指定要翻译的源语言&#xf…

2.27数据结构

1.链队 //link_que.c #include "link_que.h"//创建链队 Q_p create_que() {Q_p q (Q_p)malloc(sizeof(Q));if(qNULL){printf("空间申请失败\n");return NULL;}node_p L(node_p)malloc(sizeof(node));if(LNULL){printf("申请空间失败\n");return…

Spring中的事务和事务的传播机制

事务是一组操作的集合&#xff0c;不可以被分割。事务会把所有的操作作为一个整体&#xff0c;这组操作要么全部成功&#xff0c;要么全部失败。 事务有三种操作&#xff1a; 开启事务&#xff1b;提交事务&#xff1b;回滚事务。 如果代码的执行逻辑是这样&#xff1a; 开…

[C++][C++11][四] -- [lambda表达式]

目录 1.为什么要有lambda表达式&#xff1f;2.lambda表达式3.lambda表达式语法4.函数对象与lambda表达式 1.为什么要有lambda表达式&#xff1f; 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法 如果待排序元素为自定义类型&am…

车牌识别-只用opencv的方式

项目简述 本文描述如何只使用opencv将车牌中的车牌号提取出来&#xff0c;整个过程大致分为三个过程&#xff1a;车牌定位&#xff0c;车牌号元素分割&#xff0c;模式匹配。 在做完这个实验后&#xff0c;我感触是&#xff0c;只用opencv的方式能使用的场景有限&#xff0c;不…

大模型(LLM)的token学习记录-I

文章目录 基本概念什么是token?如何理解token的长度&#xff1f;使用openai tokenizer 观察token的相关信息open ai的模型 token的特点token如何映射到数值&#xff1f;token级操作&#xff1a;精确地操作文本token 设计的局限性 tokenizationtoken 数量对LLM 的影响训练模型参…

【MySQL】DCL

DCL英文全称是Data Control Language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访问权限。 1. 管理用户 在MySQL数据库中&#xff0c;DCL&#xff08;数据控制语言&#xff09;是用来管理用户和权限的语句集合。通过DCL语句&#xff0c;可以创建、修改、删…

C# 打包nuget包

类库等项目开发好之后打开csproj&#xff0c;添加如下代码 <PropertyGroup><!--<TargetFramework>netstandard2.0</TargetFramework>--><PackageId>Test01</PackageId><Version>1.0.0</Version><Authors>wjl</Autho…

安防视频监控EasyCVR平台使用GB28181协议接入时,如何正确配置端口?

国标GB28181协议EasyCVR安防视频监控平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0c;平台支持7*24小时实时高清视频监控&#xff0c;能同时播放多路监控视频流…