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 on
    remote->pressUndo();    // 输出:The light is off

    // 通过遥控器关闭灯
    remote->setCommand(lightOff);
    remote->pressButton();  // 输出:The light is off
    remote->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.mfbz.cn/a/886848.html

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

相关文章

使用python基于DeepLabv3实现对图片进行语义分割

DeepLabv3 介绍 DeepLabv3 是一种先进的语义分割模型&#xff0c;由 Google Research 团队提出。它在 DeepLab 系列模型的基础上进行了改进&#xff0c;旨在提高图像中像素级分类的准确性。以下是 DeepLabv3 的详细介绍&#xff1a; 概述DeepLabv3 是 DeepLab 系列中的第三代…

设计模式-策略模式-200

优点&#xff1a;用来消除 if-else、switch 等多重判断的代码&#xff0c;消除 if-else、switch 多重判断 可以有效应对代码的复杂性。 缺点&#xff1a;会增加类的数量&#xff0c;有的时候没必要为了消除几个if-else而增加很多类&#xff0c;尤其是那些类型又长又臭的 原始代…

基于vue框架的大学生四六级学习网站设计与实现i8o8z(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;学生,训练听力,学习单词,单词分类,阅读文章,文章类型,学习课程 开题报告内容 基于Vue框架的大学生四六级学习网站设计与实现开题报告 一、研究背景与意义 随着全球化进程的加速和国际交流的日益频繁&#xff0c;英语作为国际通用语言…

【前端开发入门】html快速入门

目录 引言一、html基础模板内容二、html文档流三、html 标签1.块级元素2.行内元素3.功能性元素4.标签嵌套 四、html编码习惯五、总结 引言 本系列教程旨在帮助一些零基础的玩家快速上手前端开发。基于我自学的经验会删减部分使用频率不高的内容&#xff0c;并不代表这部分内容不…

vue.js 原生js app端实现图片旋转、放大、缩小、拖拽

效果图&#xff1a; 旋转 放大&#xff1a;手机上可以双指放大缩小 拖拽 代码实现&#xff1a; html <div id"home" class"" v-cloak><!-- 上面三个按钮 图片自己解决 --><div class"headImage" v-if"showBtn">&l…

数据订阅与消费中间件Canal 服务搭建(docker)

MySQL Bin-log开启 进入mysql容器 docker exec -it mysql5.7 bash开启mysql的binlog cd /etc/mysql/mysql.conf.dvi mysqld.cnf #在文件末尾处添加如下配置&#xff08;如果没有这个文件就创建一个&#xff09; [mysqld] # 开启 binlog log-binmysql-bin #log-bin/var/lib/mys…

Linux集群部署RabbitMQ

目录 一、准备三台虚拟机&#xff0c;配置相同 1、所有主机都需要hosts文件解析 2、所有主机安装erLang和rabbitmq 3、修改配置文件 4、导入rabbitmq 的管理界面 5、查看节点状态 6、设置erlang运行节点 7、rabitmq2和rabbitmq3重启服务 8、查看各个节点状态 二、添加…

LC刷题专题:二叉树;迭代;递归(897、1372、208)

文章目录 897.递增顺序搜索树1372. 二叉树中的最长交错路径208. 实现 Trie (前缀树) 897.递增顺序搜索树 https://leetcode.cn/problems/increasing-order-search-tree/description/ 这道题目本身就是一个简单题&#xff1a;非常容易实现&#xff1a;只需要在递归或者迭代中序…

基于spring boot的篮球论坛系统

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

每日一练:地下城游戏

174. 地下城游戏 - 力扣&#xff08;LeetCode&#xff09; 题目要求&#xff1a; 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔…

telnet发送邮件教程:安全配置与操作指南?

telnet发送邮件的详细步骤&#xff1f;怎么用telnet命令发邮件&#xff1f; 尽管现代邮件客户端和服务器提供了丰富的功能和安全性保障&#xff0c;但在某些特定场景下&#xff0c;了解如何使用telnet发送邮件仍然是一项有价值的技能。AokSend将详细介绍如何安全配置和操作tel…

数字电路week1

数字电路学习 一.电路基础 1.数字电路仿真软件-digital digital官网&#xff1a;https://github.com/hneemann/Digital?tabreadme-ov-file 建议使用红绿色盲模式 2.异或门 输入1输入2输出000011101110 简单来说就是判断两个输入是否相同 异或门的组成&#xff1a; 异或…

C语言 动态数据结构的C语言实现内存映像

C程序的内存映像 C程序中变量的内存分配方式  C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量 C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量  在栈上分配  存放函数参数值&#xff0c;局部变量值等  …

国外电商系统开发-运维系统功能清单开发

一、最终效果图 二、功能清单 功能 描述 自定义日志绘图 根据Nginx、Apache登录日志文件绘图&#xff0c;绘图数据包括&#xff1a;访问量走势&#xff0c;500错误&#xff0c;200正确百分比等 创建服务器 加入服务器 主机状态自动检查 加入主机到系统后&#xff0c;系统…

机器学习:opencv--摄像头OCR

目录 前言 一、三个函数 1.显示图像 2.点排序 3.透视变换 二、代码实例 1.打开摄像头 2.图像预处理 3.检测特定轮廓 4.对轮廓进行处理 5.释放资源 前言 摄像头OCR指的是利用摄像头捕捉图像中的文字信息&#xff0c;并通过光学字符识别&#xff08;OCR&#xff09;技…

深度学习----------------------------编码器、解码器架构

目录 重新考察CNN重新考察RNN编码器-解码器架构总结编码器解码器架构编码器解码器合并编码器和解码器 重新考察CNN 编码器&#xff1a;将输入编码成中间表达形式&#xff08;特征&#xff09; 解码器&#xff1a;将中间表示解码成输出。 重新考察RNN 编码器&#xff1a;将文…

CSS 盒子属性

1. 盒子模型组成 1.1 边框属性 1.1.1 四边分开写 1.1.2 合并线框 1.1.3 边框影响盒子大小 1.2 内边距 注意&#xff1a; 1.3 外边距 1.3.1 嵌套块元素垂直外边距的塌陷 1.4 清除内外边距 1.5 总结

EasyExcel使用介绍

EasyExcel使用 1、EasyExcel介绍 1.1 官网介绍 传统操作Excel大多都是利用Apach POI进行操作的&#xff0c;但是POI框架并不完善&#xff0c;使用过程非常繁琐且有较多的缺陷&#xff1a; 动态操作Excel非常繁琐,对于新手来说&#xff0c;很难在短时间内上手;读写时需要占用…

二叉树深度学习——将二叉搜索树转化为排序的双向链表

1.题目解析 题目来源&#xff1a;LCR 155.将二叉搜索树转化为排序的双向链表 测试用例 2.算法原理 首先题目要求原地进行修改并且要求左指针代表前驱指针&#xff0c;右指针代表后继指针&#xff0c;所以思路就是 1.使用前序遍历创建两个指针cur、prev代表当前节点与前一个节点…

Stable Diffusion绘画 | 来训练属于自己的模型:炼丹参数调整--步数设置与计算

要想训练一个优质的模型&#xff0c;一定要认识和了解模型训练中&#xff0c;参数的作用和意义。 整个模型训练的过程&#xff0c;参数并不是一成不变的&#xff0c;也没有固定的模板&#xff0c; 当我们修改了模型训练里面的某个参数&#xff0c;很可能就需要连带其他一系列…