Qt-命令模式

本文详细介绍了如何使用Qt实现命令模式,通过遥控器控制灯光为例,阐述了命令模式的核心概念和应用场景。文章内容包括命令模式的定义、类图、角色解释以及具体的代码实现,展示了如何创建命令对象、请求者、接收者等。此外,还讨论了命令模式支持撤销操作的实现,并给出了宏命令的示例,以增强命令模式的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

命令模式

    定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。


类图


客户角色(Client): 创建具体的命令对象,并且设置命令对象的接收者。

命令角色(Command): 定义命令的接口,声明执行的方法。这是一个抽象类。

具体命令角色(ConcreteCommand):命令接口实现对象,是“虚”的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

请求者角色(Invoker要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

接收者角色(Receiver):接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。


例子:


根据大多数例子就是 遥控器和饭店点餐,这里使用遥控器。

先看个 很丑的 遥控器图



根据介绍,命令模式是一个解耦的模式。

假设这个界面是遥控器,那么我们这些按钮执行的函数永远是一样的,不变的。

不会因为我想让第一个按钮打开 厨房灯,而却 更改 触发第一个按钮的内容。

请参照我上传的资源 (半夜上传没有审核啊,不知道百度网盘连接能用不:http://pan.baidu.com/s/1i5xzZKD)

来看 CommandPattern(1)

在这个遥控器例,我们的按钮槽函数永远不变:

void RemoteControl::on_pushButton_clicked()
{
    m_pInvoker->doOnCommand(0);
}

void RemoteControl::on_pushButton_2_clicked()
{
    m_pInvoker->doOffCommand(0);
}

void RemoteControl::on_pushButton_3_clicked()
{
    m_pInvoker->doOnCommand(1);
}

void RemoteControl::on_pushButton_4_clicked()
{
    m_pInvoker->doOffCommand(1);
}
...
...
void RemoteControl::on_pushButton_15_clicked()
{
    m_pInvoker->doUndo();
}

那么我们怎么通过触发第一个按钮就实现 客厅开灯这个操作?

我们用一个类Invoker 来管理操作命令, 这里有两组 一个是开,一个是关。

Invoker.h

public:
    NoCommand * m_pNoCommand;        // 未定义命令
    QVector<ICommand *> onCommands;  // "开" 命令组
    QVector<ICommand *> offCommands; // "关" 命令组
public:
    // 设置遥控器 按键 对应的 开命令 关命令
    void setCommand(int slot, ICommand *onCommand, ICommand *offCommand);
    void doOnCommand(int slot);   // "开" 命令 的执行
    void doOffCommand(int slot);  // "关" 命令 的执行
Invoker.cpp 具体实现:

Invoker::Invoker()
{
    m_pNoCommand = new NoCommand;
    // 初始化 开 关 两组命令
    for(int i = 0; i < SLOTNUMBER; i++)
    {
        onCommands.push_back(m_pNoCommand);
        offCommands.push_b
<< 命令模式(Command Pattern)是一种行为设计模式,它将请求封装为对象,并使发出者与接收者解耦。这种方式使得我们可以参数化其他对象、队列或记录日志等。 在Qt中使用C++实现命令模式时,我们通常会结合信号槽机制一起使用。以下是如何用Qt和C++实现命令模式的一个简单示例: ```cpp #include <QObject> #include <QDebug> // 定义一个抽象基类 Command class Command : public QObject { Q_OBJECT public: explicit Command(QObject *receiver = nullptr) : receiver_(receiver) {} virtual ~Command() {} virtual void execute() = 0; protected: QObject* receiver_; }; // 具体的命令 ConcreteCommandA 和 ConcreteCommandB class ConcreteCommandA : public Command { Q_OBJECT public: explicit ConcreteCommandA(QObject *receiver) : Command(receiver) {} void execute() override { qDebug() << "ConcreteCommandA executed!"; if (receiver_) { // 使用 Qt 的 signal/slot 来调用 Receiver 的功能 emit doSomething(); } } signals: void doSomething(); }; class ConcreteCommandB : public Command { Q_OBJECT public: explicit ConcreteCommandB(QObject *receiver) : Command(receiver) {} void execute() override { qDebug() << "ConcreteCommandB executed!"; if (receiver_) { emit undoSomething(); } } signals: void undoSomething(); }; // 接收器 Receiver 类 class Receiver : public QObject { Q_OBJECT public slots: void actionA() { qDebug() << "Receiver performs Action A"; } void actionB() { qDebug() << "Receiver performs Action B"; } }; int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 创建 Receiver 实例 Receiver receiver; // 创建具体的命令实例并关联到 Receiver 上 auto commandA = new ConcreteCommandA(&receiver); auto commandB = new ConcreteCommandB(&receiver); // 连接命令中的信号到 Receiver 中的方法上 QObject::connect(commandA, &ConcreteCommandA::doSomething, &receiver, &Receiver::actionA); QObject::connect(commandB, &ConcreteCommandB::undoSomething, &receiver, &Receiver::actionB); // 执行命令 commandA->execute(); // 输出: ConcreteCommandA executed! / Receiver performs Action A commandB->execute(); // 输出: ConcreteCommandB executed! / Receiver performs Action B return app.exec(); } #include "main.moc" ``` ### 解释 1. **Command 抽象类** 是所有具体命令的基础接口,定义了一个 `execute()` 方法用于执行操作。 2. **ConcreteCommands** 是实现了实际业务逻辑的具体命令子类,在这里分别对应于两个不同类型的指令。 3. **Receiver** 则是真正执行这些动作的目标对象;它可以被多个不同类型的具体命令所控制。 4. 在主程序里创建了相关的对象后,通过连接各个组件之间的关系(即绑定Signal/Slot),最终完成了整个过程——当某个特定类型的动作被执行时,相应地触发相应的响应处理函数。 这种架构有助于扩展性和维护性的提升,因为新增加的功能只需添加新的Concrete Commands而无需改动现有代码结构太多内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值