设计模式_命令模式

命令模式(Command Pattern)详解

命令模式是一种行为设计模式,它将请求或操作封装为对象,从而使你可以参数化客户端对象,对请求排队或记录请求日志,以及支持可撤销的操作。

核心概念

  1. 命令(Command):声明执行操作的接口
  2. 具体命令(Concrete Command):将接收者对象与动作绑定
  3. 接收者(Receiver):知道如何执行与请求相关的操作
  4. 调用者(Invoker):要求命令对象执行请求
  5. 客户端(Client):创建具体命令对象并设置其接收者

模式结构

Invoker
|__ command: Command
|__ executeCommand()

Command (Interface/Abstract Class)
|__ execute()
|__ undo()

ConcreteCommand
|__ execute()
|__ undo()
|__ receiver: Receiver

Receiver
|__ action()

实现示例(C++)

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

// 接收者类 - 电灯
class Light {
public:
    void on() {
        std::cout << "电灯打开了" << std::endl;
    }
    
    void off() {
        std::cout << "电灯关闭了" << std::endl;
    }
};

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

// 具体命令 - 开灯命令
class LightOnCommand : public Command {
public:
    explicit LightOnCommand(Light* light) : light_(light) {}
    
    void execute() override {
        light_->on();
    }
    
    void undo() override {
        light_->off();
    }

private:
    Light* light_;
};

// 具体命令 - 关灯命令
class LightOffCommand : public Command {
public:
    explicit LightOffCommand(Light* light) : light_(light) {}
    
    void execute() override {
        light_->off();
    }
    
    void undo() override {
        light_->on();
    }

private:
    Light* light_;
};

// 调用者 - 遥控器
class RemoteControl {
public:
    void setCommand(std::shared_ptr<Command> command) {
        command_ = command;
    }
    
    void pressButton() {
        command_->execute();
        commandHistory_.push_back(command_);
    }
    
    void pressUndo() {
        if (!commandHistory_.empty()) {
            commandHistory_.back()->undo();
            commandHistory_.pop_back();
        }
    }

private:
    std::shared_ptr<Command> command_;
    std::vector<std::shared_ptr<Command>> commandHistory_;
};

// 客户端代码
int main() {
    // 创建接收者
    Light livingRoomLight;
    
    // 创建具体命令
    auto lightOn = std::make_shared<LightOnCommand>(&livingRoomLight);
    auto lightOff = std::make_shared<LightOffCommand>(&livingRoomLight);
    
    // 创建调用者
    RemoteControl remote;
    
    // 测试开灯
    remote.setCommand(lightOn);
    remote.pressButton(); // 开灯
    
    // 测试关灯
    remote.setCommand(lightOff);
    remote.pressButton(); // 关灯
    
    // 测试撤销
    remote.pressUndo(); // 撤销关灯(即开灯)
    remote.pressUndo(); // 撤销开灯(即关灯)
    
    return 0;
}

命令模式优点

  1. 解耦:分离调用操作的对象和知道如何执行操作的对象
  2. 可扩展:可以轻松添加新命令而不改变现有代码
  3. 支持撤销/重做:可以实现命令的撤销和重做功能
  4. 支持事务:可以将一组命令组合成一个复合命令
  5. 支持队列和日志:可以实现命令的排队执行和日志记录

适用场景

  1. 需要将操作表示为对象时
  2. 需要支持撤销/重做操作时
  3. 需要支持事务或命令排队时
  4. 需要实现回调机制时
  5. 需要记录操作历史时

现实生活例子:餐厅点餐系统

// 接收者 - 厨师
class Chef {
public:
    void cookPasta() {
        std::cout << "厨师正在做意大利面" << std::endl;
    }
    
    void cookSteak() {
        std::cout << "厨师正在做牛排" << std::endl;
    }
};

// 具体命令 - 做意大利面命令
class CookPastaCommand : public Command {
public:
    explicit CookPastaCommand(Chef* chef) : chef_(chef) {}
    
    void execute() override {
        chef_->cookPasta();
    }
    
    void undo() override {
        std::cout << "撤销意大利面订单" << std::endl;
    }

private:
    Chef* chef_;
};

// 具体命令 - 做牛排命令
class CookSteakCommand : public Command {
public:
    explicit CookSteakCommand(Chef* chef) : chef_(chef) {}
    
    void execute() override {
        chef_->cookSteak();
    }
    
    void undo() override {
        std::cout << "撤销牛排订单" << std::endl;
    }

private:
    Chef* chef_;
};

// 调用者 - 服务员
class Waiter {
public:
    void takeOrder(std::shared_ptr<Command> order) {
        orders_.push_back(order);
    }
    
    void submitOrders() {
        for (auto& order : orders_) {
            order->execute();
        }
        orders_.clear();
    }

private:
    std::vector<std::shared_ptr<Command>> orders_;
};

// 使用示例
int main() {
    Chef chef;
    Waiter waiter;
    
    auto pastaOrder = std::make_shared<CookPastaCommand>(&chef);
    auto steakOrder = std::make_shared<CookSteakCommand>(&chef);
    
    waiter.takeOrder(pastaOrder);
    waiter.takeOrder(steakOrder);
    
    waiter.submitOrders(); // 厨师开始烹饪
    
    return 0;
}

命令模式通过将请求封装为对象,提供了更大的灵活性和控制能力,使得请求的发送者和接收者解耦,同时支持撤销、事务等高级功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值