设计模式-05 设计模式-命令行设计模式 Command Pattern

设计模式-05 设计模式-命令行设计模式 Command Pattern 
 

(1)定义

命令模式是一种设计模式,它将请求封装成一个对象,从而使您可以用不同的方式参数化请求、队列请求以及支持可撤销的操作。

命令模式将一个请求封装成一个对象,从而使您可以用不同的方式参数化请求、队列请求以及支持可撤销的操作。
将请求封装成对象:命令模式将每个请求封装成一个独立的对象,称为“命令”对象。
参数化请求:命令对象可以存储与请求相关的所有信息,包括接收者、动作和任何其他必要的参数。
队列请求:命令对象可以存储在一个队列中,以便按顺序或并发执行。
支持可撤销的操作:命令对象可以实现一个“撤销”方法,允许撤销先前执行的请求。


+----------------+
| Command        |
+----------------+
| - execute()    |
+----------------+

+----------------+
| ConcreteCommand |
+----------------+
| - execute()    |
+----------------+

+----------------+
| Invoker        |
+----------------+
| - addCommand()  |
| - invokeCommands() |
+----------------+

+----------------+
| Receiver        |
+----------------+
| - action()      |
+----------------+

调用关系:

Invoker 类拥有一个 Command 对象的集合。
当 Invoker 的 invokeCommands() 方法被调用时,它将依次调用集合中每个 Command 对象的 execute() 方法。
Command 对象的 execute() 方法负责调用 Receiver 对象的 action() 方法来执行实际操作。

 

        +----------------+
          | Invoker        |
          +----------------+
               |
               v
+----------------+  +----------------+  +----------------+
| Command        |  | ConcreteCommand |  | Command        |
+----------------+  +----------------+  +----------------+
               |                              |
               v                              v
+----------------+                          +----------------+
| Receiver       |                         | Receiver       |
+----------------+                          +----------------+


        图示中,Invoker 类调用 ConcreteCommand 对象的 execute() 方法,然后 ConcreteCommand 对象调用 Receiver 对象的 action() 方法来执行实际操作。


2.内涵

命令模式通常由以下类组成:

  • Command:抽象命令接口,定义执行请求的方法。
  • ConcreteCommand:实现 Command 接口的具体命令类,封装特定请求。
  • Invoker:调用命令对象并管理它们的执行。
  • Receiver:执行命令的实际对象。

3.使用示例

#include <iostream>
#include <vector>

// Command 接口
class Command {
public:
    virtual void execute() = 0;
};

// ConcreteCommand 类
class ConcreteCommand : public Command {
private:
    std::string _parameter;

public:
    ConcreteCommand(const std::string& parameter) : _parameter(parameter) {}

    void execute() override {
        std::cout << "Executing command with parameter: " << _parameter << std::endl;
    }
};

// Invoker 类
class Invoker {
private:
    std::vector<Command> _commands;

public:
    void addCommand(Command command) {
        _commands.push_back(command);
    }

    void invokeCommands() {
        for (auto command : _commands) {
            command->execute();
        }
    }
};

int main() {
    // 创建命令对象
    Command command1 = new ConcreteCommand("Hello");
    Command command2 = new ConcreteCommand("World");

    // 创建调用者对象
    Invoker invoker;

    // 将命令添加到调用者
    invoker.addCommand(command1);
    invoker.addCommand(command2);

    // 调用命令
    invoker.invokeCommands();

    // 清理
    delete command1;
    delete command2;

    return 0;
}

4.注意事项

使用命令模式需要考虑注意事项:

  • 命令对象可能变得复杂:如果命令需要执行复杂的操作或依赖于大量数据,则命令对象可能变得复杂且难以维护。
  • 命令队列可能会变得庞大:如果需要执行大量命令,则命令队列可能会变得庞大且难以管理。
  • 命令模式可能会引入额外的开销:由于每个请求都需要创建一个命令对象,因此命令模式可能会引入额外的开销。
  • 撤销和重做操作可能很复杂:实现撤销和重做操作可能很复杂,尤其是在命令之间的依赖关系的情况下。
  • 命令模式可能不适用于所有场景:命令模式最适合处理明确定义的请求,不适合处理需要动态或交互式行为的场景。

其他注意事项:

  • 命令模式最适合于具有明确命令和接收者分离的场景。
  • 如果命令之间存在复杂的关系,则命令模式可能不适合。
  • 命令模式可能不适用于需要高性能的场景。

5.最佳实践

命令模式最佳实践:

  • 使用命令封装请求:将每个请求封装在自己的命令对象中,以保持请求的独立性和可重用性。
  • 将命令与接收者解耦:命令对象不应直接依赖于接收者对象。相反,命令应该通过接口或抽象基类与接收者交互。
  • 使用命令队列:当需要按顺序或并行执行多个命令时,可以使用命令队列。
  • 考虑撤销和重做操作:如果需要,可以实现撤销和重做操作,以允许用户撤销或重做先前执行的命令。
  • 使用宏命令:宏命令可以将多个命令组合成一个单一的命令,从而简化复杂操作的执行。
  • 保持命令对象轻量级:命令对象应尽可能保持轻量级,只包含执行请求所需的信息。
  • 使用工厂方法创建命令:使用工厂方法可以简化命令创建过程,尤其是当有多种类型的命令时。
  • 测试命令:编写单元测试以验证命令的正确性和健壮性。
6.总结

命令模式是一种有用的设计模式,可以提高代码的可测试性和可维护性,但重要的是要了解其注意事项并在适当的情况下使用它。

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

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

相关文章

TCP三次握手四次挥手 UDP

TCP是面向链接的协议&#xff0c;而UDP是无连接的协议 TCP的三次握手 三次传输过程是纯粹的不涉及数据&#xff0c;三次握手的几个数据包中不包含数据内容。它的应用层&#xff0c;数据部分是空的&#xff0c;只是TCP实现会话建立&#xff0c;点到点的连接 TCP的四次挥手 第四…

介绍 ffmpeg.dll 文件以及ffmpeg.dll丢失怎么办的五种修复方法

ffmpeg.dll 是一个动态链接库文件&#xff0c;属于 FFmpeg运行库。它在计算机上扮演着非常重要的角色&#xff0c;因为它提供了许多应用程序和操作系统所需的功能和组件。当 ffmpeg.dll 文件丢失或损坏时&#xff0c;可能会导致程序无法正常运行&#xff0c;甚至系统崩溃。下面…

基于opencv的车辆统计

车辆统计&#xff09; 一、项目背景二、整体流程三、常用滤波器的特点四、背景减除五、形态学开运算闭运算 六、项目完整代码七、参考资料 一、项目背景 检测并识别视频中来往车辆的数量 最终效果图&#xff1a; 二、整体流程 加载视频图像预处理&#xff08;去噪、背景减除…

航空电子FC节点卡, FC交换机,主要采用LC或MPO光纤接口形式

FC节点卡主要采用LC或MPO光纤接口形式&#xff0c;可以作为4/2个独立端口使用&#xff0c;也可以作为2对/1对冗余端口使用&#xff0c;支持1.0625Gbps、2.125Gbps、4.25Gbps、8.5Gbps通信速率。节点卡完全遵循FC-LS&#xff0c;FC-FS&#xff0c;FC-AE-ASM、FC-AE-1553B等FC光纤…

springboot+vue+mybatis家教管理系统的设计与实现+PPT+论文+讲解+售后

家教管理系统是为了方便用户能够在网站上查看教师信息进行家教预约等&#xff0c;于是开发了基于springboot框架设计与实现了一款简洁、轻便的家教管理系统。本系统解决了家教管理事务中的主要问题&#xff0c;包括以下多个功能模块&#xff1a;公告信息、留言信息、预约家教老…

Isaac Sim 4 键盘控制小车前进方向(学习笔记5.8.2)

写的乱糟糟&#xff0c;主要是这两周忘了记录了...吭哧吭哧往下搞&#xff0c;突然想起来要留档&#xff0c;先大致写一个&#xff0c;后面再往里添加和修改吧&#xff0c;再不写就全忘了 有一个一直没解决的问题&#xff1a; 在保存文件时出现问题&#xff1a;isaac sim mism…

【OceanBase诊断调优】—— 磁盘性能问题导致卡合并和磁盘写入拒绝排查

适用版本 OceanBase 数据库 V3.x、V4.x 版本。 问题现象 OceanBase 集群合并一直未完成&#xff0c;同时 tsar 和 iostat 显示从凌晨 2:30 开始磁盘使用率一直是 100%。怀疑合并导致 IO 上升&#xff0c;IO 可能存在问题&#xff0c;observer.log 的确有大量报错 disk is hu…

概述篇——计算机网络学习笔记(基于谢希仁教材与PPT)

教材用的是谢希仁的教材&#xff0c;图片来源于谢希仁老师配套的PPT 计算机网络课程PPT&#xff08;通过这个链接&#xff0c;你可以找到课程配套的ppt&#xff09; 计算机网络的定义及其特点 定义 网络 过去大众熟知的三种网络分别是提供电话、电报及传真等服务的电信网络&am…

Linux主机排查工具-GScan

0x01 简介 本程序旨在为安全应急响应人员对Linux主机排查时提供便利&#xff0c;实现主机侧Checklist的自动全面化检测&#xff0c;根据检测结果自动数据聚合&#xff0c;进行黑客攻击路径溯源。 0x02 项目地址 https://github.com/grayddq/GScan 0x03 CheckList检测项 自…

每日一题——力扣面试题 17.04. 消失的数字

题目链接&#xff1a;https://leetcode.cn/problems/missing-number-lcci/description/ 菜鸡做法&#xff1a; #include <stdlib.h> // 包含标准库头文件&#xff0c;用于内存分配等功能// 函数定义&#xff1a;寻找缺失的数字 int missingNumber(int* nums, int numsSi…

从离线到实时:无锡锡商银行基于 Apache Doris 的数据仓库演进实践

作者&#xff1a;武基鹏&#xff0c;无锡锡商银行 大数据技术经理 编辑整理&#xff1a;SelectDB 技术团队 导读&#xff1a;为实现数据资产的价值转化以及全面数字化、智能化的风险管理&#xff0c;无锡锡商银行大数据平台经历从 Hive 离线数据仓库到 Apache Doris 实时数据仓…

Hive SQL-DQL-Select查询语句用法详解

HQL Select用法详解 1.基础语法 &#xff08;1&#xff09;select_exp &#xff08;2&#xff09;ALL、DISTINCT &#xff08;3&#xff09;WHERE &#xff08;4&#xff09;分区查询、分区裁剪 &#xff08;5&#xff09;GROUP BY &#xff08;6&#xff09;HAVING &#xff0…

hadoop学习---基于Hive的教育平台数据仓库分析案例(三)

衔接第一部分&#xff0c;第一部分请点击&#xff1a;基于Hive的教育平台数据仓库分析案例&#xff08;一) 衔接第二部分&#xff0c;第二部分请点击&#xff1a;基于Hive的教育平台数据仓库分析案例&#xff08;二) 学生出勤模块&#xff08;全量分析&#xff09;&#xff1a…

Densenet+SE

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊# 前言 前言 这周开始学习关于经典模型的改进如加注意力机制&#xff0c;这周学习Densenet加通道注意力即SE注意力机制。 ##SE注意力机制简介 SE&#xff08;…

自定义shell

1、首先我们的程序要打印出命令行 命令行》用户名【主机名】当前路劲$:命令字符串 用户名、主机名、当前路径可以通过系统调用函数getenv()得到&#xff1a; 2、获取命令字符串 把输入的命令字符串放到一个指针数组中 但是我们发现用scanf函数输入的话&#xff0c;遇到空…

【数据结构】-- 链表专题

链表的分类 前面我们实现了单链表&#xff0c;单链表只是链表的一种。可以根据以下几个标准来判断链表的类型&#xff1a; 1.单向或者双向 如图所示&#xff0c;单向链表中一个节点的指针域只储存了下一个节点的指针&#xff0c;能通过前一个节点访问后一个节点&#xff0c;无…

Vue 3.3 编译宏 vue3.3新增了一些语法糖和宏,包括泛型组件、defineSlots、defineEmits、defineOptions

Vue 3.3新增了一些语法糖和宏&#xff0c;包括泛型组件、defineSlots、defineEmits、defineOptions defineProps 父组件传参 <template><Child name"my"></Child> </template> <script setup lang"ts"> import Child fro…

使用Docker安装Yapi接口管理工具

简介&#xff1a; YAPI 是由去哪儿网移动架构组开发的一款可视化接口管理工具。它具有可视化管理、高效易用、功能强大等特点。它提供了便捷的接口创建、发布和维护方式&#xff0c;开发人员可以通过简单的操作实现接口管理。 YAPI 还支持类似 postman 的接口调试&#xff0c;对…

06-数组

1. 为什么需要数组 一个养鸡场有6只鸡&#xff0c;它们的体重分别是3kg&#xff0c;4kg&#xff0c;1kg&#xff0c;2kg&#xff0c;6kg&#xff0c;3kg。 没有数组&#xff0c;就需要定义六个变量&#xff0c;一个变量代表一只鸡的体重。 使用数组&#xff0c;就可以定义一…

TypeScript学习日志-第二十三天(装饰器Decorator)

装饰器Decorator 一、类装饰器 ClassDecorator 其中返回的 target 是 Http 的构造函数&#xff0c;有了构造函数就不会去破坏其自身原有的结构&#xff0c;当我们 Http 里面有多个属性或者方法的&#xff0c;当是我们不想看或者改变它&#xff0c;这时候可以在构造函数中增加即…
最新文章