Qt C++设计模式->命令模式

命令模式(Command Pattern)是一种行为型设计模式,它将一个请求封装为一个对象,从而使你可以用不同的请求对客户端进行参数化,对请求排队或记录请求日志,并支持可撤销的操作。命令模式通过将请求的发送者与执行者解耦,赋予了系统更强的灵活性和可扩展性。

命令模式的应用场景

命令模式常用于以下场景:

  • 撤销操作:可以将命令封装起来,支持撤销和恢复操作。

  • 任务队列:可以对命令进行排队处理,例如任务调度系统。

  • 宏命令:可以将一组命令打包为一个复杂的操作,例如在游戏或复杂应用中执行一系列操作。

命令模式允许请求发送者和接收者完全解耦,发送者只需负责将命令发出,接收者如何处理命令并不影响发送者的操作。

命令模式的核心结构

命令模式的关键参与者有以下几种:

  1. 命令接口(Command):定义了执行请求的方法,所有具体命令类都实现该接口。

  2. 具体命令(Concrete Command):实现了命令接口,持有对接收者对象的引用,执行具体的操作。

  3. 接收者(Receiver):执行命令实际逻辑的对象。

  4. 调用者(Invoker):负责调用命令,通常包含一个命令对象的引用。

命令模式示例代码

假设你在开发一个智能家居系统,其中有灯光设备,用户可以通过不同的命令来打开或关闭灯光。命令模式将这些操作封装为对象,允许你对命令进行操作(如记录、撤销等)。

#include <QDebug>
#include <QString>// 接收者类:灯
class Light {
public:void turnOn() {qDebug() << "The light is on";}void turnOff() {qDebug() << "The light is off";}
};// 命令接口
class Command {
public:virtual void execute() = 0;  // 执行命令virtual void undo() = 0;     // 撤销命令virtual ~Command() = default;
};// 具体命令类:打开灯光命令
class LightOnCommand : public Command {
private:Light* light;  // 持有接收者对象public:LightOnCommand(Light* light) : light(light) {}void execute() override {light->turnOn();  // 执行打开灯光的操作}void undo() override {light->turnOff();  // 撤销打开灯光的操作}
};// 具体命令类:关闭灯光命令
class LightOffCommand : public Command {
private:Light* light;  // 持有接收者对象public:LightOffCommand(Light* light) : light(light) {}void execute() override {light->turnOff();  // 执行关闭灯光的操作}void undo() override {light->turnOn();  // 撤销关闭灯光的操作}
};// 调用者类:遥控器
class RemoteControl {
private:Command* command;  // 持有当前命令public:void setCommand(Command* command) {this->command = command;  // 设置要执行的命令}void pressButton() {if (command) {command->execute();  // 执行命令}}void pressUndo() {if (command) {command->undo();  // 撤销命令}}
};// 使用示例
int main() {// 创建接收者Light* livingRoomLight = new Light();// 创建具体命令Command* lightOn = new LightOnCommand(livingRoomLight);Command* lightOff = new LightOffCommand(livingRoomLight);// 创建调用者RemoteControl* remote = new RemoteControl();// 通过遥控器打开灯remote->setCommand(lightOn);remote->pressButton();  // 输出:The light is onremote->pressUndo();    // 输出:The light is off// 通过遥控器关闭灯remote->setCommand(lightOff);remote->pressButton();  // 输出:The light is offremote->pressUndo();    // 输出:The light is on// 清理内存delete lightOn;delete lightOff;delete livingRoomLight;delete remote;return 0;
}

代码解析

  • Light类:这是接收者类,包含具体的逻辑操作(打开和关闭灯光)。

  • Command接口:定义了executeundo方法,所有的具体命令都必须实现这些方法。

  • LightOnCommand和LightOffCommand类:具体命令类,分别封装了打开和关闭灯光的操作,内部持有接收者Light对象。

  • RemoteControl类:这是调用者,负责调用命令。它可以设置命令并执行或撤销该命令。

  • 客户端代码:客户端通过将不同的命令设置给RemoteControl,可以执行不同的操作,并支持撤销命令。

命令模式的优点

  • 解耦请求发送者和接收者:命令模式将请求发送者与接收者完全解耦,发送者只知道如何发出请求,而不需要知道如何处理请求。

  • 支持撤销和重做:由于命令对象封装了具体操作,命令模式天然支持撤销和重做操作。

  • 扩展性强:可以轻松添加新命令,而不需要改变现有代码。只需要添加新的命令类,实现命令接口即可。

  • 支持宏命令:命令模式可以组合多个命令,从而实现复杂操作的宏命令。

命令模式的缺点

  • 命令类增多:对于每个不同的请求,都需要定义一个新的命令类,可能会导致命令类数量过多,增加系统复杂性。

  • 增加内存开销:因为每一个请求都需要封装为一个对象,可能会导致内存开销增加,尤其是当命令比较复杂时。

适合使用命令模式的情况

  • 需要对请求排队、记录日志或撤销操作:例如任务调度系统、日志系统、编辑器中的撤销操作等。

  • 需要参数化请求:可以通过不同的命令对象,将请求封装为参数传递给调用者。

  • 需要将一系列操作封装为宏命令:例如在复杂应用中(如游戏、绘图软件等),可以将一组操作封装为一个宏命令,并在某个时刻统一执行。

Qt中的命令模式应用

在Qt开发中,命令模式可以用于事件处理、撤销操作、任务调度等场景。例如,在图形界面应用中,命令模式可以用于封装对控件的操作,从而实现撤销/重做功能。此外,Qt的信号与槽机制也具有类似命令模式的思想,信号发出时由槽来处理事件,从而解耦了事件发送者与处理者。

命令模式通过将请求封装为对象,提供了灵活的请求处理机制,尤其适合需要对请求进行管理、撤销或组合的场景。

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

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

相关文章

protobuf 讲解

一、序列化概念回顾 二、什么是PB 将结构化数据进行序列化的一种方式 三、PB的特点 语言无关、平台无关&#xff1a;即PB支持Java&#xff0c;C、Python等多种语言。支持多个平台 高效&#xff1a;即比XML更小&#xff0c;更快&#xff0c;更为简单。 扩展性、兼容性好&am…

WPF之UI进阶--控件样式与样式模板及词典

WPF的优势之一就是能够更加容易快捷的对窗体和控件的外面进行改造&#xff0c;换句话说&#xff0c;那就是UI设计个性化更加容易。主要是借助了样式、模板及词典来实现的。那么本篇博文就一一对他们进行介绍。 文章目录 一、样式1: 定义样式2: 使用Setter设置属性关于Property和…

C或C++判断指针是否指向同一块内存

有时需要判断指针是否指同一块内存&#xff0c;例如设计字符串时&#xff1a; &#xff08;1&#xff09;insert函数 &#xff08;2) replace函数 &#xff08;3&#xff09;assign函数 难点是迭代器&#xff0c;判断是否同一个迭代器时&#xff0c;需要你在设计迭代器时加…

Kubernetes-环境篇-01-mac开发环境搭建

1、brew安装 参考知乎文章&#xff1a;https://zhuanlan.zhihu.com/p/111014448 苹果电脑 常规安装脚本&#xff08;推荐 完全体 几分钟安装完成&#xff09; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"苹果电脑 极…

Rstudio:强大的R语言集成开发环境(IDE)

Rstudio 应该是 R 语言使用的标配&#xff0c;尽管 Rstudio 的母公司 Posit 推出了新一代的集成开发环境 Positron&#xff0c;但其还处于开发阶段。作为用户不妨让其成熟后再使用&#xff0c;现阶段还是 Rstudio 更稳定。 如果你在生物信息学或统计学领域工作&#xff0c;R语言…

Python | Leetcode Python题解之第455题分发饼干

题目&#xff1a; 题解&#xff1a; class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:g.sort()s.sort()m, n len(g), len(s)i j count 0while i < m and j < n:while j < n and g[i] > s[j]:j 1if j < n:count 1i …

uni-app - - - - -vue3使用i18n配置国际化语言

uni-app - - - - -使用i18n配置国际化语言 1. 安装vue-i18n2. 配置文件2.1 创建如下文件2.2 文件配置2.3 main文件导入i18n 3. 页面内使用3.1 template内直接使用3.2 变量接收使用 1. 安装vue-i18n npm install vue-i18n --save2. 配置文件 2.1 创建如下文件 locales文件夹里…

水泵模块(5V STM32)

目录 一、介绍 二、传感器原理 1.尺寸介绍 2.继电器控制水泵电路原理图 三、程序设计 main.c文件 bump.h文件 bump.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 水泵模块(bump)通常是指用于液体输送系统的组件&#xff0c;它负责将水或其他流体从低处提…

四.网络层(上)

目录 4.1网络层功能概述 4.2 SDN基本概念 4.3 路由算法与路由协议 4.3.1什么是路由协议&#xff1f; 4.3.2什么是路由算法&#xff1f; 4.3.3路由算法分类 (1)静态路由算法 (2)动态路由算法 ①全局性 OSPF协议与链路状态算法 ②分散性 RIP协议与距离向量算法 4.3.…

【C语言】内存函数的使用和模拟实现

文章目录 一、memcpy的使用和模拟实现二、memmove的使用和模拟实现三、memset的使用四、memcmp的使用 一、memcpy的使用和模拟实现 在之前我们学习了使用和模拟实现strncpy函数&#xff0c;它是一个字符串函数&#xff0c;用来按照给定的字节个数来拷贝字符串&#xff0c;那么问…

【本地免费】SimpleTex 图像识别latex公式

文章目录 相关教程相关文献安装教程 由于mathpix开始收费了&#xff0c;于是本文将介绍一款目前本地免费的SimpleTex工具 相关教程 【超详细安装教程】LaTeX-OCR 图像识别latex公式&#xff08;开源免费&#xff09;_latex图片识别-CSDN博客 相关文献 SimpleTex主页——致力…

数据结构双向链表和循环链表

目录 一、循环链表二、双向链表三、循环双向链表 一、循环链表 循环链表就是首尾相接的的链表&#xff0c;就是尾节点的指针域指向头节点使整个链表形成一个循环&#xff0c;这就弥补了以前单链表无法在后面某个节点找到前面的节点&#xff0c;可以从任意一个节点找到目标节点…

5.3 克拉默法则、逆矩阵和体积

本节是使用代数而不是消元法来求解 A x b A\boldsymbol x\boldsymbol b Axb 和 A − 1 A^{-1} A−1。所有的公式都会除以 det ⁡ A \det A detA&#xff0c; A − 1 A^{-1} A−1 和 A − 1 b A^{-1}\boldsymbol b A−1b 中的每个元素都是一个行列式除以 A A A 的行列式。…

C(十一)scanf、getchar(第三弹)

问题引入&#xff1a;如何实现输入一串密码&#xff0c;如&#xff1a;“123 xxxx” &#xff0c;然后读取并确认&#xff0c;是 -- Y&#xff1b;否 -- N。 自然的&#xff0c;我们想到用scanf&#xff0c;但是在使用过程中你是否遇到跟我一样的困惑呢&#xff1f;如下&…

如何高效删除 MySQL 日志表中的历史数据?实战指南

在处理高并发的物联网平台或者其他日志密集型应用时&#xff0c;数据库中的日志表往往会迅速增长&#xff0c;数据量庞大到数百GB甚至更高&#xff0c;严重影响数据库性能。如何有效管理这些庞大的日志数据&#xff0c;特别是在不影响在线业务的情况下&#xff0c;成为了一项技…

【LeetCode HOT 100】详细题解之二叉树篇

【LeetCode HOT 100】详细题解之二叉树篇 94 二叉树的中序遍历方法一&#xff1a;递归方法二&#xff1a;迭代 104 二叉树的最大深度方法一&#xff1a;递归方法二&#xff1a;迭代 226 翻转二叉树方法一&#xff1a;递归方法二&#xff1a;迭代 101 对称二叉树方法一&#xff…

小程序-使用npm包

目录 Vant Weapp 安装 Vant 组件库 使用 Vant 组件 定制全局主题样式 API Promise化 1. 基于回调函数的异步 API 的缺点 2. 什么是 API Promise 化 3. 实现 API Promise 化 4.调用 Promise 化之后的异步 API 小程序对 npm 的支持与限制 目前&#xff0c;小程序中已经…

Java 之深入理解 String、StringBuilder、StringBuffer

前言 由于发现 String、StringBuilder、StringBuffer 面试的时候会经常问到&#xff0c;这里就顺便总结一下&#xff1a;本文重点会以这三个字符串类的性能、线程安全、存储结构这三个方面进行分析 ✨上期回顾&#xff1a;Java 哈希表 ✨目录 前言 String 介绍 String 的不可变…

全局安装cnpm并设置其使用淘宝镜像的仓库地址(地址最新版)

npm、cnpm和pnpm基本概念 首先介绍一下npm和cnpm是什么&#xff0c;顺便说一下pnpm。 npm npm&#xff08;Node Package Manager&#xff09;是Node.js的默认包管理器&#xff0c;用于安装、管理和分享JavaScript代码包。它是全球最大的开源库生态系统之一&#xff0c;提供了数…

如何使用ssm实现基于HTML的中国传统面食介绍网站的搭建+vue

TOC ssm758基于HTML的中国传统面食介绍网站的搭建vue 第1章 绪论 1.1选题动因 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔…