跳转到内容

C++ 命令模式

来自代码酷
Admin留言 | 贡献2025年4月28日 (一) 21:31的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)


命令模式(Command Pattern)是行为型设计模式的一种,它将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,支持请求的排队、记录、撤销和重做等操作。在C++中,命令模式常用于解耦调用者(Invoker)和执行者(Receiver),使系统更灵活、可扩展。

基本概念[编辑 | 编辑源代码]

命令模式的核心思想是将操作请求实际执行分离。它包含以下主要角色:

  • Command(命令接口):声明执行操作的接口。
  • ConcreteCommand(具体命令):实现命令接口,绑定一个接收者(Receiver)和动作。
  • Receiver(接收者):知道如何执行与请求相关的操作。
  • Invoker(调用者):存储命令对象并在适当时机触发命令。
  • Client(客户端):创建具体命令并设置其接收者。

类图表示[编辑 | 编辑源代码]

classDiagram class Command { +execute() void } class ConcreteCommand { -receiver: Receiver +execute() void } class Receiver { +action() void } class Invoker { -command: Command +setCommand(Command) void +executeCommand() void } class Client { } Command <|-- ConcreteCommand ConcreteCommand o-- Receiver Invoker o-- Command Client ..> ConcreteCommand Client ..> Receiver

代码示例[编辑 | 编辑源代码]

以下是一个简单的C++实现,展示命令模式的基本结构:

#include <iostream>
#include <memory>

// 接收者类
class Light {
public:
    void turnOn() {
        std::cout << "Light is ON" << std::endl;
    }
    void turnOff() {
        std::cout << "Light is OFF" << std::endl;
    }
};

// 命令接口
class Command {
public:
    virtual ~Command() = default;
    virtual void execute() = 0;
};

// 具体命令:开灯
class TurnOnCommand : public Command {
    Light& light;
public:
    explicit TurnOnCommand(Light& l) : light(l) {}
    void execute() override {
        light.turnOn();
    }
};

// 具体命令:关灯
class TurnOffCommand : public Command {
    Light& light;
public:
    explicit TurnOffCommand(Light& l) : light(l) {}
    void execute() override {
        light.turnOff();
    }
};

// 调用者
class RemoteControl {
    std::unique_ptr<Command> command;
public:
    void setCommand(std::unique_ptr<Command> cmd) {
        command = std::move(cmd);
    }
    void pressButton() {
        if (command) {
            command->execute();
        }
    }
};

int main() {
    Light light;
    RemoteControl remote;

    // 设置开灯命令并执行
    remote.setCommand(std::make_unique<TurnOnCommand>(light));
    remote.pressButton(); // 输出: Light is ON

    // 设置关灯命令并执行
    remote.setCommand(std::make_unique<TurnOffCommand>(light));
    remote.pressButton(); // 输出: Light is OFF

    return 0;
}

输出[编辑 | 编辑源代码]

Light is ON
Light is OFF

实际应用场景[编辑 | 编辑源代码]

命令模式在以下场景中特别有用:

1. GUI按钮操作:每个按钮绑定一个命令对象,点击时触发执行。 2. 事务系统:支持命令的撤销(Undo)和重做(Redo)。 3. 任务队列:将命令对象存入队列,异步执行。

案例:支持撤销的操作[编辑 | 编辑源代码]

扩展上述代码,增加撤销功能:

// 带撤销的命令接口
class UndoableCommand : public Command {
public:
    virtual void undo() = 0;
};

// 具体命令:调整亮度
class DimLightCommand : public UndoableCommand {
    Light& light;
    int prevLevel;
public:
    explicit DimLightCommand(Light& l) : light(l), prevLevel(0) {}
    void execute() override {
        prevLevel = 50; // 假设保存当前亮度
        std::cout << "Dimming light to 50%" << std::endl;
    }
    void undo() override {
        std::cout << "Restoring light to " << prevLevel << "%" << std::endl;
    }
};

// 客户端使用
int main() {
    Light light;
    RemoteControl remote;
    auto dimCommand = std::make_unique<DimLightCommand>(light);

    remote.setCommand(std::move(dimCommand));
    remote.pressButton(); // 输出: Dimming light to 50%

    // 假设通过其他方式获取命令指针进行撤销
    dynamic_cast<UndoableCommand*>(remote.getCommand())->undo(); // 输出: Restoring light to 0%
}

数学表示[编辑 | 编辑源代码]

命令模式可以形式化表示为: {Command=(execute)ConcreteCommand=(execute,receiver)execute()receiver.action()

优缺点[编辑 | 编辑源代码]

优点:

  • 解耦调用者和接收者。
  • 支持命令的排队、日志、撤销/重做。
  • 易于扩展新命令。

缺点:

  • 每个命令需要一个单独的类,可能增加代码量。

总结[编辑 | 编辑源代码]

命令模式是C++中实现行为参数化的强大工具,尤其适合需要支持撤销、事务或宏操作的场景。通过将请求封装为对象,它提供了更高的灵活性和可维护性。