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

news/2024/10/7 17:29:18/

命令模式(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.ppmy.cn/news/1535794.html

相关文章

python.tkinter设计标记语言(渲染5-列表)

TOC 前言 本文只作为笔记记录。 列表文本是一个较为独立的文本块&#xff0c;但是内部包含层级关系。在新版TinML设计中&#xff0c;使用一个标签表示整个列表文本块。 <ls>list-1; |list-2; |...|不同的层级在列表行文本前加|确定&#xff0c;一级列表不需要|&#…

javacv FFmpegFrameGrabber 阻塞重连解决方法汇总

JavaCV中FrameGrabber类可以连接直播流地址, 进行解码, 获取Frame帧信息, 常用方式如下 FrameGrabber grabber new FrameGrabber("rtsp:/192.168.0.0"); while(true) {Frame frame grabber.grabImage();// ... } 在如上代码中, 若连接地址网络不通, 或者连接超时…

高速机器人的点动与直线运动

工业机器人中的点动和直线运动非常之重要&#xff0c;接下来说一下他们的实现过程。 点动&#xff1a; 点动包括两个部分&#xff0c;第一个点动是每一个关节电机的点动&#xff0c;第二个是机器末端向xyz的三个方向进行点动处理。 第一个点动是非常简单的&#xff0c;即把对…

Docker安装mysql8并配置主从复制

1. 安装mysql8 1.1 新增挂载文件 # 新增mysql挂载文件夹 mkdir -p /root/docker/mysql/m01/log mkdir -p /root/docker/mysql/m01/data mkdir -p /root/docker/mysql/m01/conf1.2 新增mysql配置文件 # 新增mysql配置文件 cd /root/docker/mysql/m01/conf vim my.cnf # 下面是…

stm32四足机器人(标准库)

项目技术要求 PWM波形的学习 参考文章stm32 TIM输出比较(PWM驱动LED呼吸灯&&PWM驱动舵机&&PWM驱动直流电机)_ttl pwm 驱动激光头区别-CSDN博客 舵机的学习 参考文章 stm32 TIM输出比较(PWM驱动LED呼吸灯&&PWM驱动舵机&&PWM驱动直流电机)…

太速科技-FMCJ457-基于JESD204B的2路2Gsps AD 2路2Gsps DA FMC子卡

FMCJ457-基于JESD204B的2路2Gsps AD 2路2Gsps DA FMC子卡 一、板卡概述 该子卡是高速AD9172 DAC和AD9689 ADC的FMC板。为客户提供高达2 GHz 的可用模拟带宽以及 JESD204B 接口&#xff0c;以快速地对各种宽带 RF 应用进行原型制作。 AD芯片AD9689&#xff0c;AD9689-2…

Qt中使用QPainter绘制阴影

困扰了很久的问题&#xff0c;今天终于明白了如何绘制QGraphicDropShadowEffect同样效果的阴影&#xff0c;故写下这篇文章分享给大家。其方法是复制Qt源代码中QGraphicDropShadowEffect绘制实现的核心代码然后稍作修改实现&#xff0c;先看效果和封装过后的源代码&#xff1a;…

Final Glory推出“荣耀勋章-神龙”,推动游戏叙事范式发展

GameFi赛道因基建设施的缺失而长期处于加密市场的边缘位置&#xff0c;该叙事在市场中的占有率正在下降。不过好的一面是&#xff0c;随着MetaArena引擎面向市场&#xff0c;正在推动区块链游戏市场的叙事向全新的范式发展。 MetaArena引擎是以零知识证明方案为基础的Web3游戏基…