命令设计模式(Command Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

news2024/11/23 19:47:22

文章目录

  • 概念
  • 组成角色
  • 相关图示
  • 示例代码
  • 框架中的运用
  • 适用场景

概念

        命令设计模式(Command Pattern)是一种行为设计模式,它将请求的操作封装为一个对象,从而实现请求者和执行者之间的解耦。这样,请求者只需要知道如何发送请求,而无需关心请求的具体执行过程。命令模式在很多场景下都非常有用,例如撤销操作、延迟执行、记录操作日志等。

组成角色

  1. 抽象命令(Command):定义命令的接口,通常包含一个名为execute()的方法。
  2. 具体命令(ConcreteCommand):实现抽象命令接口,封装具体的操作逻辑。
  3. 请求者(Invoker):负责调用命令对象来执行请求,通常不需要知道命令的具体实现。
  4. 接收者(Receiver):负责执行具体的操作,通常是一个具体的类或对象。

相关图示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgMmyPLS-1681788037192)(/Users/dasouche/Library/Application Support/typora-user-images/image-20230417175954613.png)]

示例代码

// 抽象命令
interface Command {
    void execute();
}

// 具体命令
class ConcreteCommand implements Command {
    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.action();
    }
}

// 接收者
class Receiver {
    void action() {
        System.out.println("执行具体操作");
    }
}

// 请求者
class Invoker {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void invoke() {
        command.execute();
    }
}

// 客户端代码
public class CommandPatternDemo {
    public static void main(String[] args) {
      
      //**在这个示例中,我们定义了一个抽象命令Command接口和一个具体命令ConcreteCommand类。具体命令封装了接收者Receiver的操作逻辑。请求者Invoker负责调用命令对象来执行请求。客户端代码创建了接收者、具体命令和请求者,并通过调用请求者的invoke()方法来执行请求。这样,请求者和接收者之间实现了解耦,使得代码更加灵活、易于维护。**/
      	
        // 创建接收者
        Receiver receiver = new Receiver();
        // 创建具体命令
        Command command = new ConcreteCommand(receiver);
        // 创建请求者
        Invoker invoker = new Invoker();
        invoker.setCommand(command);
        // 执行请求
        invoker.invoke();
    }
}

框架中的运用

在Dubbo框架中,命令模式被用于处理网络通信中的请求和响应。下面是相关流程中的简版代码

1、org.apache.dubbo.remoting.exchange.ExchangeChannel接口。这是Dubbo通信层中的一个关键接口,它代表了一个通信通道。其中,request(Object request)方法用于发送请求,而send(Object message)方法用于发送响应:

public interface ExchangeChannel extends Channel {
    CompletableFuture<Object> request(Object request) throws RemotingException;
    CompletableFuture<Object> request(Object request, int timeout) throws RemotingException;
    void send(Object message) throws RemotingException;
		// 省略部分代码...
}

2、当通道收到一个请求或响应时,它会将其封装为org.apache.dubbo.remoting.exchange.Requestorg.apache.dubbo.remoting.exchange.Response对象。这两个类分别表示请求和响应,其中Request类包含请求的数据以及请求的ID,而Response类包含响应的数据、状态以及请求的ID:

public class Request {
    private final long id;
    private String version;
    private boolean twoWay = true;
    private boolean event = false;
    private Object data;
     // 省略部分代码...
}

public class Response {
    private final long id;
    private String version;
    private int status;
    private boolean event = false;
    private Object result;
    private Throwable exception;
    // 省略部分代码...
}

3、在通信层,有一个org.apache.dubbo.remoting.Dispatcher接口,它负责分发请求和响应。分发器会将收到的请求和响应封装为ChannelHandler对象,并调用相应的方法进行处理。例如,当分发器收到一个请求时,它会调用ChannelHandlerreceived(Channel channel, Object message)方法进行处理:

public interface ChannelHandler {
    void connected(Channel channel) throws RemotingException;
    void disconnected(Channel channel) throws RemotingException;
    void sent(Channel channel, Object message) throws RemotingException;
    void received(Channel channel, Object message) throws RemotingException;
    void caught(Channel channel, Throwable exception) throws RemotingException;
}

4、对于请求的处理,通常会使用org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler类。这个类实现了ChannelHandler接口,并重写了received(Channel channel, Object message)方法。在这个方法中,它首先判断收到的消息是否为Request对象,然后根据请求的类型(如普通请求、心跳请求等)进行相应的处理:

public class HeaderExchangeHandler implements ChannelHandlerDelegate {
  	
  //展示相关代码
  @Override
  public void received(Channel channel, Object message) throws RemotingException {
      if (message instanceof Request) {
					//省略部分代码
          // 处理请求
          handleRequest(channel, (Request) message);
      } else if (message instanceof Response) {
          // 处理响应
          handleResponse(channel, (Response) message);
      } else {
					//省略部分代码
          // 对于其他类型的消息,调用父类的方法进行处理
          handler.received(channel, message);
      }
  }
  
 

}

适用场景

  1. 请求调用者与请求接收者需要解耦:命令模式将调用操作的对象与知道如何实现这些操作的对象分离开来,这有助于降低系统各部分之间的耦合。
  2. 需要抽象出待执行的操作以参数化其他对象:命令模式可以将请求封装为具体的命令对象,这些对象可以在运行时进行传递、组合和替换,实现了更高程度的灵活性。
  3. 需要支持撤销操作:命令模式可以在命令接口中添加一个名为undo的方法,以便在需要时撤销操作。具体命令类可以保存先前的状态,以便在执行undo方法时能够恢复原始状态。
  4. 需要支持宏命令:命令模式允许将多个命令组合成一个宏命令对象,即一个命令序列。这个宏命令对象可以像单个命令一样被执行,从而实现对一组命令的统一管理。
  5. 需要将命令放入队列中进行排队执行:命令模式可以将命令对象放入队列中,然后逐个执行这些命令。这可以帮助实现后台任务队列、工作线程池等功能。
  6. 需要记录命令日志:命令模式可以用于记录命令的详细信息,这有助于实现日志记录、审计、事务等功能。

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

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

相关文章

Darknet19详细原理(含tensorflow版源码)

Darknet19原理 Darknet19是一个轻量级的卷积神经网络&#xff0c;用于图像分类和检测任务。 它是YOLOv2目标检测算法的主干网络&#xff0c;它的优点在于具有较少的参数和计算量&#xff0c;在计算速度和精度之间取得了良好的平衡&#xff0c;同时在训练过程中也具有较高的准确…

MobileNetV1详细原理(含torch源码)

目录 MobileNetV1原理 MobileNet V1的网络结构如下&#xff1a; 为什么要设计MobileNet&#xff1a; MobileNetV1的主要特点如下&#xff1a; MobileNetV1的创新点&#xff1a; MobileNetV1源码&#xff08;torch版&#xff09; 训练10个epoch的效果 MobileNetV1原理 Mo…

玩转ChatGPT:中科院ChatGPT Academic项目部署与测评

一、ChatGPT Academic简介 最近&#xff0c;以ChatGPT为代表的超大规模语言模型火出了圈&#xff0c;各种二次开发项目也是层出不穷。 比如说今天我们玩弄的这个“ChatGPT Academic”&#xff0c;在GitHub上已经13.7K的点赞了。 项目地址&#xff1a;https://github.com/bina…

因为这5大工具,同事直呼我时间管理小王子

写在前面 关于时间管理、如何做计划、如何提高执行力等等相关话题其实很早之前我就想写了&#xff0c;但一直拖着迟迟没有动笔。 在之前的一篇文章里我曾详细聊过自己对于时间管理&#xff0c;如何提高执行力&#xff0c;以及如何摆脱那种没有灵魂的任务计划的一些思考和做法…

【C语言】深度理解指针(中)

前言✈ 上回说到&#xff0c;我们学习了一些与指针相关的数据类型&#xff0c;如指针数组&#xff0c;数组指针&#xff0c;函数指针等等&#xff0c;我们还学习了转移表的基本概念&#xff0c;学会了如何利用转移表来实现一个简易计算器。详情请点击传送门&#xff1a;【C语言…

Windows 下安装和使用Redis

Redis 一般安装在Linux中&#xff0c; 但有时出于学习和其他目的&#xff0c;需要在Windows机器运行Redis&#xff0c; 本篇介绍如果在&#xff37;indows中运行和使用Redis。 关于Redis的基本介绍可以参考&#xff1a; Redis介绍、安装与初体验 Windows 下Redis的下载 可…

【NestJs】日志收集

Nest 附带一个默认的内部日志记录器实现&#xff0c;它在实例化过程中以及在一些不同的情况下使用&#xff0c;比如发生异常等等&#xff08;例如系统记录&#xff09;。这由 nestjs/common 包中的 Logger 类实现。你可以全面控制如下的日志系统的行为&#xff1a; 完全禁用日…

jenkins windows安装 部署项目 前端 后端

安装 需要安装的程序&#xff1a; 1.下载jenkins windows版本 2.400 此版本需要jdk11 https://www.jenkins.io/ 按着提示安装即可 2.下载jdk 11 https://login.oracle.com/ 按着提示安装即可 部署pc 1.新建项目 2.源码管理 3.添加git用户 4.Build Steps 构建 初始化np…

vue2数据响应式原理(2)搭建webpack认识一下Object.defineProperty

在1中我们讲到 Object.defineProperty() 是vue2实现数据响应的关键 那么我们就来好好的看看这个方法 方法字面意思是定义属性 而他是通过Object对象调用的 所以说 他是用来控制对象的某个属性的 比较官方的解释是 object.defineProperty() 方法会直接在一个对象上定义一个新属…

单片机添加版本号的一些小技巧

平时我们写程序&#xff0c;通常都会备注软件版本&#xff0c;那么&#xff0c;怎么在单片机中保存版本信息呢&#xff1f; 方法其实有很多&#xff0c;但基本原理都是在指定存储区域&#xff08;Flash&#xff09;中写入软件版本信息。 实现方法 下面就分享一个最常用&#xf…

算法风险防控

算法风险防控是指在算法应用过程中&#xff0c;通过对算法应用场景、数据、模型和结果等多个方面的风险进行评估和控制&#xff0c;以保障算法应用的安全性、可靠性和合法性。以下是一些常见的算法风险防控措施&#xff1a; 数据风险防控&#xff1a;在算法应用中&#xff0c;…

【python】Python基础入门:从变量到异常处理

天池实验室代码链接&#xff1a;https://tianchi.aliyun.com/notebook-ai/home#notebookLabId491001 简介 Python 是一种通用编程语言&#xff0c;其在科学计算和机器学习领域具有广泛的应用。如果我们打算利用 Python 来执行机器学习&#xff0c;那么对 Python 有一些基本的了…

51单片机定时器与计数器

文章目录 51单片机定时器与计数器一、定时器与计数器的结构与功能计数功能定时功能 二、定时器与计数器的控制TMOD 工作方式寄存器TCON 定时器控制寄存器 三、仿真案例(一).8个LED 1 秒周期闪烁。(二) 产品包装生产线。 51单片机定时器与计数器 一、定时器与计数器的结构与功能…

ESP32设备驱动-BMP388气压传感器驱动

BMP388气压传感器驱动 文章目录 BMP388气压传感器驱动1、BMP388介绍2、硬件准备3、软件准备4、驱动实现1、BMP388介绍 BMP388 是一款非常小巧、低功耗和低噪声的 24 位绝对气压传感器。 它可以实现精确的高度跟踪,特别适合无人机应用。 BMP388 在 0-65C 之间的同类最佳 TCO,…

港联证券|AI概念板块无死角杀跌,主题炒作熄火后资金会流向哪些板块?

ChatGPT概念指数大跌7%&#xff0c;单日跌幅创历史之最。 4月10日&#xff0c;炒作逾月的ChatGPT概念板块团体大跌&#xff0c;云从科技&#xff08;688327.SH&#xff09;、三六零&#xff08;601360.SH&#xff09;、科大讯飞&#xff08;002230.SZ&#xff09;等热门股跌停&…

集中式版本控制工具 —— SVN

一、简介 1️⃣ SVN 是什么&#xff1f; 代码版本管理工具他能记住每次的修改查看所有的修改记录恢复到任何历史版本恢复已经删除的文件 2️⃣ SVN 与 Git 相比有什么优势&#xff1f; 使用简单、上手快目录级权限控制&#xff0c;企业安全必备子目录 Checkout&#xff0c;…

RK3568平台开发系列讲解(Linux系统篇)文件系统的读写

🚀返回专栏总目录 文章目录 一、文件IO1.1、文件 IO read()1.2、文件 IO write()二、系统调用层和虚拟文件系统层三、ext4 文件系统层沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们一起学习 read 和 write 调用过程。 一、文件IO 1.1、文件 IO read() rea…

openLdap2.4.44的安装部署

openLdap2.4.44的安装部署 一、安装 1.从yum源拉取 yum install -y openldap openldap-clients openldap-servers 2.复制DB到指定目录 cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG 3.给目录授权 &#xff08;如果没有ldap &#xff0c;可…

定时任务框架快速入门

一、Quartz 1. Quartz 概述 Quartz 是一个开源的作业调度框架(job scheduler)&#xff0c;几乎可以集成到任何 Java 应用程序中&#xff0c;从最小的独立应用程序到最大的电子商务系统。Quartz 可用于创建简单或复杂的调度来执行数十个、数百个甚至数万个作业&#xff1b;其任务…

[NOIP1999 普及组] Cantor 表

[NOIP1999 普及组] Cantor 表 题目描述: 现代数学的著名证明之一是 Georg Cantor 证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的&#xff1a; 1/1 , 1/2 , 1/3 , 1/4, 1/5, … 2/1, 2/2 , 2/3, 2/4, … 3/1 , 3/2, 3/3, … 4…