通知图标

欢迎访问津桥芝士站

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

该帖子部分内容已隐藏
付费阅读
3积分
此内容为付费阅读,请付费后查看
来自AI助手的总结
命令模式通过将请求封装成对象来解耦请求发送者与处理者,支持撤销、宏命令等功能,增强代码灵活性但可能增加系统复杂性。

一、引言

命令模式(Command Pattern)是一种行为型设计模式,它将一个请求封装为一个对象,从而使用户可以使用不同的请求、队列或日志来参数化其他对象。通过命令模式,程序可以实现请求的排队、记录请求日志以及支持可撤销操作。

二、使用场景

  1. 需要支持撤销和重做操作:命令模式非常适合处理那些需要提供撤销功能的场景,例如在文本编辑器中执行的多个操作。

  2. 请求调用的调用者与接受者之间的解耦:在需要将请求的发送者与处理者解耦的情况下,命令模式提供一种有效的方式。

  3. 宏命令的执行:当需要在一系列操作中进行特定操作的组合时,命令模式可以利用命令对象批量处理相关操作。

  4. 请求的参数化:可以使用命令对象通过不同的参数化请求进行不同的处理,增强了灵活性和可扩展性。

三、模式分类

  • 简单命令模式:有简单的操作请求,包含所有操作的访问和调用接口。

  • 组合命令模式:允许多个命令合并形成一个更复杂的操作,用于执行一系列命令。

  • 宏命令模式:用于将一组命令包装成一个命令并按照顺序依次执行。

四、优缺点

优点

  • 解耦:命令模式将请求的发送者与执行者之间的耦合打散,方便代码的扩展及维护。
  • 增强的灵活性:可以根据需要在不同场合配置和修改命令执行,不需要对现有的代码做太多改动。
  • 支持撤销的操作:通过堆栈模式运用命令模式实现的撤销操作显得尤为简单。

缺点

  • 增加系统复杂性:命令模式可能导致类的数量互相交叉,一定逻辑的下游请求、响应有时难以骨骼清晰。
  • 难以实现:在涉及更复杂的命令对象时,可能需提供请求的具体细节,让实现变得更加复杂。
  • 命令结构可能庞大:如果实现的命令过多,可能导致命令体庞大并变得难以维护和扩展。

五、代码示例

以下是命令模式的C++实现示例。

#include <iostream>
#include <memory>
#include <vector>

// 命令接口
class Command {
public:
    virtual void execute() = 0;  // 执行命令的接口
    virtual ~Command() = default;  // 虚析构函数
};

// 示例接收者类 (开灯)
class Light {
public:
    void on() {
        std::cout << "Light is ON!" << std::endl;
    }

    void off() {
        std::cout << "Light is OFF!" << std::endl;
    }
};

// 具体命令类
class LightOnCommand : public Command {
private:
    Light* light;  // 接收者

public:
    LightOnCommand(Light* light) : light(light) {}  // 设置接收者

    void execute() override {
        light->on();  // 调用接收者的逻辑
    }
};

// 具体命令类
class LightOffCommand : public Command {
private:
    Light* light;  // 接收者

public:
    LightOffCommand(Light* light) : light(light) {}  // 设置接收者

    void execute() override {
        light->off();  // 调用接收者的逻辑
    }
};

// 遥控器 (用来保存命令)
class RemoteControl {
private:
    std::vector<std::shared_ptr<Command>> commandList;  // 命令存储列表

public:
    void addCommand(std::shared_ptr<Command> command) {
        commandList.push_back(command);  // 添加命令
    }

    void pressButton(int index) {
        if (index < commandList.size()) {
            commandList[index]->execute();  // 执行命令
        }
        else {
            std::cout << "No command assigned to this button!" << std::endl;
        }
    }
};

int main() {
    // 创建接收者
    auto light = std::make_unique<Light>();  // 使用 unique_ptr

    // 创建具体命令
    std::shared_ptr<Command> lightOn = std::make_shared<LightOnCommand>(light.get());
    std::shared_ptr<Command> lightOff = std::make_shared<LightOffCommand>(light.get());

    // 创建遥控器并设置命令
    RemoteControl remote;
    remote.addCommand(lightOn);   // 将命令设置为打开灯的命令
    remote.addCommand(lightOff);   // 将命令设置为关闭灯的命令

    // 模拟按下开灯按钮
    remote.pressButton(0);  // 输出 "Light is ON!"
    // 模拟按下关灯按钮
    remote.pressButton(1);  // 输出 "Light is OFF!"

    return 0;  // unique_ptr will automatically clean up light
}

代码解析

  1. Command 接口:定义了一种统一的命令接口,通过 execute() 方法用于执行命令。

  2. LightOnCommand 和 LightOffCommand:具体的命令类,负责定义打开和关闭灯的命令。命令类持有接收者(通过 light )对象的引用并执行相关逻辑。

  3. RemoteControl:中控器类,作为命令的接收和存储器,管理命令对象并提供按下按钮执行的方式。

  4. main() 函数:借助 RemoteControl 设定命令,通过 pressButton() 方法执行命令,并显示相应的操作信息。

六、模式总结

命令模式解决了请求的发送者与处理者之间的耦合,是对象请求机制中不可或缺的一部分。它的自主性使得请求能有多种处理方案,且便于复杂请求重用。虽然引入了新的类并增大了应用的复杂度,但在合适的场合使用,它依然能够增强代码的清晰度和扩展性,提供高效灵活的操作接口。通过掌握命令模式的原则,开发者能够设计出更加灵活、可维护的代码结构,带来更快速的迭代开发体验。

请登录后发表评论

    没有回复内容