《设计模式的艺术》笔记 - 命令模式

介绍

        命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为模式,其别名为动作模式或事务模式。

实现

myclass.h

//
// Created by yuwp on 2024/1/12.
//#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H#include <iostream>
#include <unordered_map>
#include <atomic>class Command { // 命令抽象类
public:virtual void execute() = 0;
};class Reciever {    // 命令接收者,可以继承实现具体的接收类
public:virtual void action();
};class ConcreteCommand : public Command {    // 具体命令类
public:ConcreteCommand();~ConcreteCommand();void execute() override;private:Reciever *m_reciever;
};class Invoker { // 调用者类,命令发送者
public:Invoker(Command *command);void call();private:Command *m_command;
};#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//#include "myclass.h"
#include <thread>
#include <unistd.h>ConcreteCommand::ConcreteCommand() {m_reciever = new Reciever();
}ConcreteCommand::~ConcreteCommand() {if (m_reciever)delete m_reciever;
}void ConcreteCommand::execute() {m_reciever->action();
}void Reciever::action() {std::cout << "接收者处理命令" << std::endl;
}Invoker::Invoker(Command *command) {m_command = command;
}void Invoker::call() {m_command->execute();
}

main.cpp

#include <iostream>
#include <mutex>
#include "myclass.h"int main() {Command *command = new ConcreteCommand();Invoker *invoker = new Invoker(command);invoker->call();return 0;
}

命令队列实现

        只需要增加一个CommandQueue类即可,Invoker中保存对CommandQueue的引用。

myclass.h

//
// Created by yuwp on 2024/1/12.
//#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>class Command { // 命令抽象类
public:virtual void execute() = 0;
};class Reciever {    // 命令接收者,可以继承实现具体的接收类
public:virtual void action();
};class ConcreteCommand : public Command {    // 具体命令类
public:ConcreteCommand();~ConcreteCommand();void execute() override;private:Reciever *m_reciever;
};class CommandQueue {
public:void execute();void addCommand(Command *command);void removeCommand(Command *command);private:std::vector<Command *> m_commands;
};class Invoker { // 调用者类,命令发送者
public:Invoker(CommandQueue *commands);void call();private:CommandQueue *m_commands;
};#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//#include "myclass.h"
#include <thread>
#include <unistd.h>ConcreteCommand::ConcreteCommand() {m_reciever = new Reciever();
}ConcreteCommand::~ConcreteCommand() {if (m_reciever)delete m_reciever;
}void ConcreteCommand::execute() {m_reciever->action();
}void Reciever::action() {std::cout << "接收者处理命令" << std::endl;
}Invoker::Invoker(CommandQueue *commands) {m_commands = commands;
}void Invoker::call() {m_commands->execute();
}void CommandQueue::execute() {for (auto it = m_commands.begin(); it != m_commands.end(); ++it) {(*it)->execute();}
}void CommandQueue::addCommand(Command *command) {m_commands.push_back(command);
}void CommandQueue::removeCommand(Command *command) {for (auto it = m_commands.begin(); it != m_commands.end(); ) {if (*it == command) {it = m_commands.erase(it);} else {++it;}}
}

main.cpp

#include <iostream>
#include <mutex>
#include "myclass.h"int main() {Command *command = new ConcreteCommand();CommandQueue *queue = new CommandQueue();queue->addCommand(command);Invoker *invoker = new Invoker(queue);invoker->call();delete invoker;delete queue;delete command;return 0;
}

撤销操作

        在命令类中增加一个逆向操作,也可以通过保存对象的历史状态来实现状态回滚。

请求日志

        执行命令时增加日志的记录操作。

宏命令

        组合模式和命令模式的结合,可以实现批量命令的执行,与命令队列类似,不同的是宏命令类继承自命令抽象类(Command),可以递归调用。

总结

优点

        1. 降低系统的耦合度。由于请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦,相同的请求者可以对应不同的接收者。同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。

        2. 新的命令可以很容易地加入系统中。由于增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码甚至客户类代码,满足开闭原则的要求。

        3. 可以比较容易地设计一个命令队列或宏命令(组合命令)。

        4. 为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。

缺点

        1. 使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个对请求接收者的调用操作都需要设计一个具体命令类,因此在某些系统中可能需要提供大量的具体命令类,这将影响命令模式的使用。

适用场景

        1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。请求调用者无须知道接收者的存在,也无须知道接收者是谁,接收者也无须关心何时被调用。

        2. 系统需要在不同的时间指定请求、将请求排队和执行请求。一个命令对象和请求的初始调用者可以有不同的生命期。换言之,最初的请求发出者可能已经不在了,而命令对象本身仍然是活动的,可以通过该命令对象去调用请求接收者,而无须关心请求调用者的存在性,可以通过请求日志文件等机制来具体实现。

        3. 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

        4. 系统需要将一组操作组合在一起形成宏命令。

练习

myclass.h

//
// Created by yuwp on 2024/1/12.
//#ifndef DESIGNPATTERNS_MYCLASS_H
#define DESIGNPATTERNS_MYCLASS_H#include <iostream>
#include <unordered_map>
#include <atomic>
#include <vector>class Command { // 命令抽象类
public:virtual void execute() = 0;
};class BoardScreen {    // 命令接收者
public:void open();void create();void edit();
};class OpenCommand : public Command {    // 具体命令类
public:OpenCommand(BoardScreen *reciever);void execute() override;private:BoardScreen *m_reciever;
};class CreateCommand : public Command {    // 具体命令类
public:CreateCommand(BoardScreen *reciever);void execute() override;private:BoardScreen *m_reciever;
};class EditCommand : public Command {    // 具体命令类
public:EditCommand(BoardScreen *reciever);void execute() override;private:BoardScreen *m_reciever;
};class Invoker { // 调用者类,命令发送者
public:Invoker(Command *command);void call();private:Command *m_command;
};#endif //DESIGNPATTERNS_MYCLASS_H

myclass.cpp

//
// Created by yuwp on 2024/1/12.
//#include "myclass.h"
#include <thread>
#include <unistd.h>void BoardScreen::open() {std::cout << "打开" << std::endl;
}void BoardScreen::create() {std::cout << "新建" << std::endl;
}void BoardScreen::edit() {std::cout << "编辑" << std::endl;
}OpenCommand::OpenCommand(BoardScreen *reciever) {m_reciever = reciever;
}void OpenCommand::execute() {m_reciever->open();
}CreateCommand::CreateCommand(BoardScreen *reciever) {m_reciever = reciever;
}void CreateCommand::execute() {m_reciever->create();
}EditCommand::EditCommand(BoardScreen *reciever) {m_reciever = reciever;
}void EditCommand::execute() {m_reciever->edit();
}Invoker::Invoker(Command *command) {m_command = command;
}void Invoker::call() {m_command->execute();
}

main.cpp

#include <iostream>
#include <mutex>
#include "myclass.h"int main() {BoardScreen *boardScreen = new BoardScreen();Command *command = new OpenCommand(boardScreen);Invoker *invoker = new Invoker(command);invoker->call();delete command;delete invoker;command = new CreateCommand(boardScreen);invoker = new Invoker(command);invoker->call();delete command;delete invoker;command = new EditCommand(boardScreen);invoker = new Invoker(command);invoker->call();delete command;delete invoker;return 0;
}

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

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

相关文章

数据预处理 matlab 数据质量评估

知乎 数据类型转换等 Mathworks 数据预处理 概念辨析 配对是同一批样本的前后比较&#xff0c;独立是两批不同样本的的比较 独立样本是指我们得到的样本是相互独立的。配对样本就是一个样本中的数据与另一个样本中的数据相对应的两个样本。配对样本可以消除由于样本指定的不公…

dpwwn:02

靶场下载地址 https://download.vulnhub.com/dpwwn/dpwwn-02.zip 环境配置 当打开此虚拟机环境的时候&#xff0c;可能会出现&#xff1a;当前硬件版本不支持设备“sata”。然后启动失败的情况~ 解决办法参考&#xff1a;https://www.cnblogs.com/yaodun55/p/16434468.html …

x-cmd pkg | fanyi - 命令行中英文翻译工具

目录 简介首次用户功能特点竞品和相关作品进一步探索 简介 fanyi 是命令行翻译工具&#xff0c;翻译数据来源于 icba.com 和 fanyi.youdao.com&#xff0c;仅支持中英文互译。支持 ChatGPT&#xff0c;可通过设置 OpenAI API 密钥以启用 ChatGPT 翻译。 注意&#xff1a;在 L…

QT上位机开发(动态数据采集与监控)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 上位机开发中,有一种类型的应用软件很特殊,它几乎没有什么交互操作,主要的工作就是检测和显示。如果说在此基础上有什么扩展的话,可能就是安全监控和报警。所以,这个上位机软件…

Flink SQL

Flink SQL 来源&#xff1a;B站尚硅谷 sql-client准备 Table API和SQL是最上层的API&#xff0c;在Flink中这两种API被集成在一起&#xff0c;SQL执行的对象也是Flink中的表&#xff08;Table&#xff09;&#xff0c;所以我们一般会认为它们是一体的。Flink是批流统一的处理…

银河麒麟V10安装mysql5.7

本文介绍如何在银河麒麟高级服务器操作系统下安装 Mysql 数据库 1.适配系统版本 适用系统&#xff1a;V10(SP1) 适用架构&#xff1a;X86、AARCH64、LOONGARCH64 其他版本和架构可作参考 2.安装说明 X86 和 AARCH 架构的源中自带 Mysql 安装包&#xff0c;所以可以下载对…

本地运行LlaMA 2的简易指南

大家好&#xff0c;像LLaMA 2这样的新开源模型已经变得相当先进&#xff0c;并且可以免费使用。可以在商业上使用它们&#xff0c;也可以根据自己的数据进行微调&#xff0c;以开发专业版本。凭借其易用性&#xff0c;现在可以在自己的设备上本地运行它们。 本文将介绍如何下载…

@RequestBody注解基础

RequestBody RequestBody注解一般与post方法使用。 一个请求中只能存在一个RequestBody注解。 RequestBody 用于接收前端传递给后端的json字符串中的数据。&#xff08;处理json格式的数据&#xff09; 语法格式&#xff1a; ​(RequestBody Map map) (RequestBody Object obje…

numpy数组的max、min、argmax和argmin计算方法

numpy数组的max、min、argmax和argmin计算方法 官方对numpy.max和numpy.min的说明 numpy.max 参考官方的理解 数组&#xff1a; 24611529 import numpy as npif __name__ __main__:a np.array([[2, 4, 6, 1], [1, 5, 2, 9]])print(a)print(np.argmax(a, axis0)) # ax…

Java医院信息管理系统

技术框架&#xff1a; springboot shiro layui jquery thymeleaf nginx 有需要的可以联系我。 运行环境&#xff1a; jdk8 mysql IntelliJ IDEA maven项目功能&#xff1a; 本项目是用springbootlayuishiro写的医院管理系统&#xff0c;系统的业务比较复杂&#x…

11 - PXC集群|MySQL存储引擎

PXC集群&#xff5c;MySQL存储引擎 数据库系列文章PXC集群配置集群测试集群 MySQL存储引擎存储引擎介绍mysql服务体系结构mysql服务的工作过程处理查询访问的工作过程处理存储insert访问的工作过程 什么是搜索引擎 存储引擎管理查看存储引擎修改存储引擎 存储引擎特点myisam存储…

canvas能压缩图片?

之前写过一篇使用命令行工具压缩图片的博文&#xff1a;使用yx-tiny命令行工具进行图片压缩&#xff0c;大家感兴趣可以去瞅一眼。 这篇简单说一下使用canvas压缩图片 其实思路很简单&#xff0c;我们选择了图片之后&#xff0c;会获取到对应的文件流对象&#xff0c;然后我们…

jvm复习,深入理解java虚拟机一:运行时数据区域

程序计数器&#xff08;Program Counter Register&#xff09; 它是程序控制流的指示器&#xff0c;简单来说&#xff0c;为了线程切换后能恢复到正确的执行位置&#xff0c;每条线程都需要有一个独立的程序计数器 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xf…

【LeetCode每日一题】2809. 使数组和小于等于 x 的最少时间

2024-1-19 文章目录 [2809. 使数组和小于等于 x 的最少时间](https://leetcode.cn/problems/minimum-time-to-make-array-sum-at-most-x/)思路&#xff1a; 2809. 使数组和小于等于 x 的最少时间 思路&#xff1a; 获取两个列表的长度n&#xff0c;并初始化一个二维数组f&…

一种更快的Kmeans原理与实现

普通的k-means实现大多需要多轮迭代,一轮需要O(n * k)的复杂度,其中n是数据量,k是聚类的数量。观察到大部分地方的标准均值中的大多数距离计算都是冗余的。 所以Elkan-Kmeans通过三角不等式来优化这一过程,减少无效计算。 困难在于三角不等式给出了上界,但我们需要下界以…

《微信小程序开发从入门到实战》学习八十六

6.15 设备API 6.15.5 屏幕亮度API 使用wx.setScreenBrightness可设置屏幕亮度。示例代码如下&#xff1a; wx.setScreenBrightness({ value: 0.5, // 屏幕亮度值&#xff0c;范围0~1,1表示最亮 success() {} }) 使用wx.getScreenBrightness可获取屏幕亮度&#xff0c;示例代…

我在提交代码的时候突然发现别人刚才提交了一点代码,我没有拉取导致问题,请问怎么解决

问: 回答: 问: 我跟随输入git pull ,然后又以下提示: Merge branch systemPower_dev of https://xxxx.com into xxxx_dev # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. …

C# 十大排序算法

以下是常见的十大排序算法&#xff08;按照学习和实现的顺序排列&#xff09;&#xff1a; 冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;希尔排序&#xff08;Shell Sort&…

LLM设计原理学习笔记

1 设计原则 &#xff08;1&#xff09;不要将多模态特征直接线性相加 博文《马毅LeCun谢赛宁曝出多模态LLM重大缺陷&#xff01;开创性研究显著增强视觉理解能力》描述了多模态encoding线性相加带来的问题&#xff1b;

推荐几种常用Web前端开发工具

工欲善其事&#xff0c;必先利其器。一个好的编辑器&#xff0c;往往能帮助开发人员提高编码效率。下面为大家推荐几款前端常用的编辑器。 1.websorm WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的H…