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

news2024/11/29 20:50:03

文章目录

  • 前言
  • 定义
  • 结构
  • 工作原理
  • 优点
  • 适用场景
  • 消息队列模式Demo实现
  • 分写业务
  • 总结

前言

定义

命令模式(Command Pattern)是一种行为型设计模式,用于将请求封装为对象,从而使你可以使用不同的请求、队列或者日志请求来参数化其他对象。这样可以实现请求的参数化操作、队列化和日志化,且能够支持撤销操作。

结构

命令模式由以下几个核心组件组成:

  • 命令(Command): 定义了执行操作的接口。通常包含一个 execute() 方法,该方法在调用时会触发接收者执行相关操作。
  • 具体命令(Concrete Command):实现命令接口,并将真正的操作委托给接收者。
  • 接收者(Receiver):负责执行实际的操作。具体命令将请求委托给接收者完成具体的业务逻辑。
  • 调用者(Invoker):负责调用命令并触发执行操作的方法。
  • 客户端(Client):创建具体命令,并将其与接收者进行绑定。
    在这里插入图片描述

工作原理

  1. 客户端创建一个具体命令,并将其与接收者(执行操作的对象)进行绑定。
  2. 调用者接收到命令后,将其存储起来,可以将命令存储在队列中,以支持撤销和重做操作。
  3. 调用者根据需要调用命令的 execute() 方法。该方法会将请求传递给接收者,由接收者执行实际的操作。
  4. 接收者执行命令所指定的操作,并完成相应的业务逻辑。

优点

  • 解耦调用者和接收者:调用者无需了解命令的具体实现,只需调用命令对象的方法来触发执行。
  • 支持撤销和重做:通过存储命令的历史记录,可以方便地进行撤销和重做操作。
  • 支持事务:可以通过一系列的命令组合形成事务,保证一组操作的原子性。

适用场景

  • 需要将请求和执行操作解耦的情况。
  • 需要支持撤销、重做、事务等操作的场景。
  • 需要将一组操作组织成具体的命令队列或日志操作。

消息队列模式Demo实现

好的,下面是一个简单的使用 Java 实现的消息队列框架示例:

import java.util.LinkedList;
import java.util.Queue;

// 消息接口
interface IMessage {
    void execute();
}

// 具体消息类
class ConcreteMessage implements IMessage {
    private String content;

    public ConcreteMessage(String content) {
        this.content = content;
    }

    public void execute() {
        System.out.println("处理消息:" + content);
    }
}

// 消息队列类
class MessageQueue {
    private Queue<IMessage> queue;

    public MessageQueue() {
        queue = new LinkedList<>();
    }

    public void enqueue(IMessage message) {
        queue.offer(message);
    }

    public IMessage dequeue() {
        return queue.poll();
    }

    public boolean isEmpty() {
        return queue.isEmpty();
    }
}

// 消费者类
class Consumer {
    private MessageQueue messageQueue;

    public Consumer(MessageQueue messageQueue) {
        this.messageQueue = messageQueue;
    }

    public void processMessages() {
        while (!messageQueue.isEmpty()) {
            IMessage message = messageQueue.dequeue();
            message.execute();
        }
    }
}

// 生产者类
class Producer {
    private MessageQueue messageQueue;

    public Producer(MessageQueue messageQueue) {
        this.messageQueue = messageQueue;
    }

    public void sendMessage(String content) {
        IMessage message = new ConcreteMessage(content);
        messageQueue.enqueue(message);
        System.out.println("发送消息:" + content);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建消息队列对象
        MessageQueue messageQueue = new MessageQueue();

        // 创建消费者对象并启动消费者线程
        Consumer consumer = new Consumer(messageQueue);
        Thread consumerThread = new Thread(consumer::processMessages);
        consumerThread.start();

        // 创建生产者对象并发送消息
        Producer producer = new Producer(messageQueue);
        producer.sendMessage("消息1");
        producer.sendMessage("消息2");
        producer.sendMessage("消息3");

        // 等待消费者线程处理完所有消息
        try {
            consumerThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在上述示例中,我们实现了一个简单的消息队列框架。IMessage 是消息接口,定义了 execute() 方法表示具体的消息处理逻辑。ConcreteMessage 是具体的消息类,实现了 IMessage 接口,并在 execute() 方法中执行具体的处理操作。

MessageQueue 是消息队列类,使用 Queue 数据结构来保存消息对象,并提供了入队、出队和判断队列是否为空的方法。

Consumer 是消费者类,通过循环从消息队列中取出消息,并调用消息对象的 execute() 方法进行处理。

Producer 是生产者类,负责向消息队列中发送消息。

在客户端代码的 main() 方法中,我们创建了一个消息队列对象,然后分别创建了消费者对象和生产者对象。生产者使用 sendMessage() 方法向消息队列发送消息,而消费者通过启动一个新线程来调用 processMessages() 方法处理消息。
在这里插入图片描述

分写业务

这个业务代码实现了一个简单的消息队列框架。下面对代码进行逐步解释:

  1. 首先,定义了一个消息接口 IMessage,其中包含了 execute() 方法用于执行具体的消息处理操作。

  2. 接着,实现了具体的消息类 ConcreteMessage,它实现了 IMessage 接口,并在 execute() 方法中执行具体的消息处理逻辑。在本例中,处理逻辑简单地打印出消息内容。

  3. 然后,定义了消息队列类 MessageQueue,使用 Queue 数据结构来保存消息对象。它提供了入队(enqueue())、出队(dequeue())和判断队列是否为空(isEmpty())的方法。

  4. 接下来,定义了消费者类 Consumer,它通过循环从消息队列中取出消息,并调用消息对象的 execute() 方法进行处理。

  5. 最后,定义了生产者类 Producer,它负责向消息队列中发送消息。通过调用 sendMessage() 方法,生产者创建一个具体的消息对象并将其加入到消息队列中,同时打印出发送的消息内容。

在客户端代码的 main() 方法中,完成以下步骤:

  1. 创建了一个消息队列对象 messageQueue

  2. 创建了消费者对象 consumer,并启动一个新线程来执行消费者的消息处理逻辑。

  3. 创建了生产者对象 producer,通过调用 sendMessage() 方法发送了三条消息。

  4. 最后,通过调用 join() 方法等待消费者线程处理完所有消息。

总结

这个示例展示了如何使用 Java 实现一个简单的消息队列框架。通过将消息封装为对象,我们可以方便地在生产者和消费者之间进行消息的传递和处理。使用消息队列框架可以实现解耦和异步处理的优势。生产者负责发送消息,消费者负责处理消息,它们通过共享的消息队列进行通信。通过多线程的方式,我们可以实现并发的消息处理,提高系统的吞吐量和响应性能。

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

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

相关文章

服务器端污染属性反射提升权限

污染属性反射检测服务器端原型污染 通过服务器端原型污染提升权限 Lab: Privilege escalation via server-side prototype pollution 必要知识点 开发人员很容易陷入的一个陷阱是忘记或忽略 JavaScript 循环迭代对象的所有可枚举属性这一事实&#xff0c;包括它通过原型链继…

医学案例|线性回归

一、案例介绍 某医师预研究糖尿病患者的总胆固醇和甘油三酯对空腹血糖的影响&#xff0c;某研究者调查40名糖尿病患者的总胆固醇、甘油三酯和空腹血糖的测量值如下&#xff0c;试根据上述研究问题作统计分析。 二、问题分析 本案例想要研究一些变量&#xff08;总胆固醇和甘油…

PocketMiner:基于深度学习发现蛋白的隐式口袋

文章目录 1. 文章简介2. 前言3. 方法3.1 模型框架 4. 结果4.1 已知隐式口袋在分子动力学模拟分析迅速打开4.2 图神经网络模型能够准确预测模拟中口袋的动态变化4.3 隐式口袋数据集数据集揭示了新的隐式口袋形成的模式4.4 PocketMiner能够从无配体的蛋白结构中精准预测预测口袋4…

2007-2022年上市公司污染排放数据/2007-2022年上市公司污染排放水平、污染排放量数据

2007-2022年上市公司污染排放数据/2007-2022年上市公司污染排放水平、污染排放量数据 1、时间&#xff1a;2007-2022年 2、指标&#xff1a;证券代码、year、化学需氧量、氨氮排放量、总氮、总磷、水体综合污染当量对数、二氧化硫、氮氧化物、烟尘、空气综合污染当量对数、总…

小游戏分发平台如何以技术拓流?

2023年&#xff0c;小游戏的发展将受到多方面的影响&#xff0c;例如新技术的引入、参与小游戏的新玩家以及游戏市场的激烈竞争等。首先&#xff0c;新技术如虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和机器人技术都可以带来新颖的游戏体验。其…

滑动窗口实例1(长度最小的子数组)

题目&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#xff1a; …

VC++使用Microsoft Speech SDK进行文字TTS朗读

Microsoft Speech SDK下载地址 https://www.microsoft.com/en-us/download/details.aspx?id=10121 需要msttss22L.exe、SpeechSDK51.exe、SpeechSDK51LangPack.exe三个,下载后全部安装 使用VS2005建立一个win32控制台项目 朗读"hello word"、中文“你好”的程序 …

百科有不需要的信息怎么删除?

百科词条的权威性众所周知&#xff0c;所以百度百科的内容审核也非常严格&#xff0c;百科营销成为目前网络营销工作中一个难点&#xff0c;很多企业无法得到自己完全满意的百度百科词条 &#xff0c;这其实也是合理的。小马识途营销顾问分析&#xff0c;百科词条内容是提供给广…

10、【WebGIS实战】图层篇——通用服务图层加载全流程(适用于全部图层)

大家好,我是X北辰北。本文是「WebGIS实战」系列,关注这个标签,阅读所有文章,成为WebGIS开发高手。 图层可以理解为添加到地图上面的数据,比如我们要在地图上展示成都市所有大型公园的位置,那么当前地图中除了初始化地图时添加的底图之外,在底图的上面我们还叠加了一份关…

HuggingFace中的 Files and versions 如何优雅下载到本地?(Python requests,tqdm)

前言 在使用huggingface把玩各种大模型时&#xff0c;如果选择从远程加载模型&#xff0c;这个过程可能因为网络问题而非常耗时甚至直接失败&#xff0c;所以把模型、分词器等相关文件下载到本地&#xff0c;再直接从本地加载就成了不可回避的流程。 在进入具体版本的模型后&…

新版Mongodb(6.0以上)找不到mongo.exe

安装目录下/bin目录中&#xff0c;没有mongo.exe文件&#xff0c;只有mongod和mongos&#xff0c;以及一个powershell命令脚本。 原因在于&#xff0c;mongodb6.0以后做出了重大改变&#xff0c;mongodb已经不再默认为你安装shell工具&#xff0c;因此需要安装一个额外的shell…

二十二、迭代器模式

一、什么是迭代器模式 迭代器&#xff08;Iterator&#xff09;模式的定义&#xff1a;迭代器模式是一种对象行为型模式&#xff0c;它提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示。   迭代器模式包含以下主要角色: 抽象聚合&…

字符串匹配的Rabin–Karp算法

leetcode-28 实现strStr() 更熟悉的字符串匹配算法可能是KMP算法, 但在Golang中,使用的是Rabin–Karp算法 一般中文译作 拉宾-卡普算法,由迈克尔拉宾与理查德卡普于1987年提出 “ 要在一段文本中找出单个模式串的一个匹配&#xff0c;此算法具有线性时间的平均复杂度&#xff0…

【XAMPP】启动数据库Error: MySQL shutdown unexpectedly.

问题&#xff1a; 启动MySQL时报错如下&#xff1a; Error: MySQL shutdown unexpectedly. This may be due to a blocked port, missing dependencies, improper privileges, a crash, or a shutdown by another method. Press the Logs button to view error logs and check…

SQL-子查询

SQL 子查询 是指将一个SELECT查询&#xff08;子查询&#xff09;的结果用括号括起来作为另一个SQL语句的数据来源或者判断条件

RK3399平台开发系列讲解(入门篇)内核模块详细加载/卸载过程

🚀返回专栏总目录 文章目录 一、 ko文件的文件格式二、内核模块加载过程三、内核模块卸载过程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍内核模块详细加载/卸载过程。 一、 ko文件的文件格式 “KO” 文件通常是指 Linux 内核模块文件,这些文件包含…

现货黄金走势图中的止盈点

对平仓时机的把握能力&#xff0c;是衡量现货黄金投资者水平的重要标志&#xff0c;止盈点设置得是否合理&#xff0c;在行情兑现的时候能否及时地离场&#xff0c;是事关投资者账户浮盈最终能否落袋为安的“头等大事”&#xff0c;要在现货黄金走势图中把握止盈点&#xff0c;…

【LeetCode-中等题】230. 二叉搜索树中第K小的元素

文章目录 题目方法一&#xff1a;层序遍历 集合排序方法二&#xff1a;中序遍历&#xff08;栈 或者 递归 &#xff09;方法三&#xff08;方法二改进&#xff09;&#xff1a;中序遍历&#xff08;栈 &#xff09; 题目 该题最大的特点就是这个树是二叉树&#xff1a; 所以…

自然语言处理(六):词的相似性和类比任务

词的相似性和类比任务 在前面的章节中&#xff0c;我们在一个小的数据集上训练了一个word2vec模型&#xff0c;并使用它为一个输入词寻找语义相似的词。实际上&#xff0c;在大型语料库上预先训练的词向量可以应用于下游的自然语言处理任务&#xff0c;为了直观地演示大型语料…

C语言:递归思想及实例详解

简介&#xff1a;在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。通过函数的自调用化繁为简。 递归可以说是编程中最神奇的一种算法。因为我们有时候可能不能完全明晰代码的运行过程&#xff0c;但是我们却知道代码可以跑出正确的结果。而当我们使…