命令模式(Command Pattern)及C++实现

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

命令模式核心结构
命令模式包含以下主要角色:

Command(命令接口):声明执行操作的接口

ConcreteCommand(具体命令):实现命令接口,绑定接收者与动作

Receiver(接收者):知道如何执行与请求相关的操作

Invoker(调用者):要求命令执行请求

Client(客户端):创建具体命令对象并设置接收者

5个经典应用场景及C++实现
1. 文本编辑器撤销/重做功能

#include <iostream>
#include <vector>
#include <string>

// 接收者:文档类
class Document {
public:
    void insertText(const std::string& text, size_t position) {
        content.insert(position, text);
        std::cout << "插入文本: " << text << " 在位置 " << position << std::endl;
    }
    
    void deleteText(size_t position, size_t length) {
        std::string deleted = content.substr(position, length);
        content.erase(position, length);
        std::cout << "删除文本: " << deleted << " 从位置 " << position << std::endl;
    }
    
    const std::string& getContent() const { return content; }

private:
    std::string content;
};

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

// 具体命令:插入文本
class InsertCommand : public Command {
public:
    InsertCommand(Document& doc, const std::string& text, size_t pos)
        : document(doc), text(text), position(pos) {}
    
    void execute() override {
        document.insertText(text, position);
    }
    
    void undo() override {
        document.deleteText(position, text.length());
    }

private:
    Document& document;
    std::string text;
    size_t position;
};

// 具体命令:删除文本
class DeleteCommand : public Command {
public:
    DeleteCommand(Document& doc, size_t pos, size_t len)
        : document(doc), position(pos), length(len), deletedText("") {}
    
    void execute() override {
        deletedText = document.getContent().substr(position, length);
        document.deleteText(position, length);
    }
    
    void undo() override {
        document.insertText(deletedText, position);
    }

private:
    Document& document;
    size_t position;
    size_t length;
    std::string deletedText;
};

// 调用者:编辑器
class Editor {
public:
    void executeCommand(Command* cmd) {
        cmd->execute();
        history.push_back(cmd);
    }
    
    void undo() {
        if (!history.empty()) {
            Command* cmd = history.back();
            cmd->undo();
            history.pop_back();
            delete cmd;
        }
    }

private:
    std::vector<Command*> history;
};

int main() {
    Document doc;
    Editor editor;
    
    // 执行命令
    editor.executeCommand(new InsertCommand(doc, "Hello", 0));
    editor.executeCommand(new InsertCommand(doc, " World", 5));
    
    std::cout << "当前文档: " << doc.getContent() << std::endl;
    
    // 撤销操作
    editor.undo();
    std::cout << "撤销后文档: " << doc.getContent() << std::endl;
    
    return 0;
}

2. 智能家居遥控器

#include <iostream>
#include <unordered_map>

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

// 接收者:风扇
class Fan {
public:
    void on() { std::cout << "风扇已打开" << std::endl; }
    void off() { std::cout << "风扇已关闭" << std::endl; }
};

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

// 具体命令:开灯
class LightOnCommand : public Command {
public:
    LightOnCommand(Light& light) : light(light) {}
    void execute() override { light.on(); }
private:
    Light& light;
};

// 具体命令:关灯
class LightOffCommand : public Command {
public:
    LightOffCommand(Light& light) : light(light) {}
    void execute() override { light.off(); }
private:
    Light& light;
};

// 具体命令:开风扇
class FanOnCommand : public Command {
public:
    FanOnCommand(Fan& fan) : fan(fan) {}
    void execute() override { fan.on(); }
private:
    Fan& fan;
};

// 具体命令:关风扇
class FanOffCommand : public Command {
public:
    FanOffCommand(Fan& fan) : fan(fan) {}
    void execute() override { fan.off(); }
private:
    Fan& fan;
};

// 调用者:遥控器
class RemoteControl {
public:
    void setCommand(int slot, Command* onCmd, Command* offCmd) {
        onCommands[slot] = onCmd;
        offCommands[slot] = offCmd;
    }
    
    void pressOnButton(int slot) {
        if (onCommands.count(slot)) {
            onCommands[slot]->execute();
        }
    }
    
    void pressOffButton(int slot) {
        if (offCommands.count(slot)) {
            offCommands[slot]->execute();
        }
    }

private:
    std::unordered_map<int, Command*> onCommands;
    std::unordered_map<int, Command*> offCommands;
};

int main() {
    Light livingRoomLight;
    Fan ceilingFan;
    
    RemoteControl remote;
    
    // 设置命令
    remote.setCommand(0, new LightOnCommand(livingRoomLight), 
                      new LightOffCommand(livingRoomLight));
    remote.setCommand(1, new FanOnCommand(ceilingFan), 
                      new FanOffCommand(ceilingFan));
    
    // 使用遥控器
    remote.pressOnButton(0);  // 开灯
    remote.pressOnButton(1);  // 开风扇
    remote.pressOffButton(0); // 关灯
    
    return 0;
}

3. 交易系统(支持撤销)

#include <iostream>
#include <stack>

// 接收者:账户
class Account {
public:
    Account(double balance = 0) : balance(balance) {}
    
    void deposit(double amount) {
        balance += amount;
        std::cout << "存入 " << amount << ", 余额: " << balance << std::endl;
    }
    
    void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
            std::cout << "取出 " << amount << ", 余额: " << balance << std::endl;
        } else {
            std::cout << "余额不足" << std::endl;
        }
    }
    
    double getBalance() const { return balance; }

private:
    double balance;
};

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

// 具体命令:存款
class Deposit : public Transaction {
public:
    Deposit(Account& acc, double amt) : account(acc), amount(amt) {}
    
    void execute() override {
        account.deposit(amount);
    }
    
    void undo() override {
        account.withdraw(amount);
    }

private:
    Account& account;
    double amount;
};

// 具体命令:取款
class Withdraw : public Transaction {
public:
    Withdraw(Account& acc, double amt) : account(acc), amount(amt) {}
    
    void execute() override {
        account.withdraw(amount);
    }
    
    void undo() override {
        account.deposit(amount);
    }

private:
    Account& account;
    double amount;
};

// 调用者:交易处理器
class TransactionProcessor {
public:
    void executeTransaction(Transaction* t) {
        t->execute();
        history.push(t);
    }
    
    void undoLastTransaction() {
        if (!history.empty()) {
            Transaction* t = history.top();
            t->undo();
            history.pop();
            delete t;
        }
    }

private:
    std::stack<Transaction*> history;
};

int main() {
    Account myAccount(1000);
    TransactionProcessor processor;
    
    processor.executeTransaction(new Deposit(myAccount, 500));
    processor.executeTransaction(new Withdraw(myAccount, 200));
    
    std::cout << "当前余额: " << myAccount.getBalance() << std::endl;
    
    processor.undoLastTransaction();
    std::cout << "撤销后余额: " << myAccount.getBalance() << std::endl;
    
    return 0;
}

4. 线程池任务调度

#include <iostream>
#include <vector>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>

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

// 具体命令:打印任务
class PrintTask : public Task {
public:
    PrintTask(const std::string& msg) : message(msg) {}
    void execute() override {
        std::cout << "执行任务: " << message << std::endl;
    }
private:
    std::string message;
};

// 具体命令:计算任务
class CalculateTask : public Task {
public:
    CalculateTask(int a, int b) : x(a), y(b) {}
    void execute() override {
        std::cout << "计算结果: " << x << " + " << y << " = " << (x + y) << std::endl;
    }
private:
    int x, y;
};

// 线程池
class ThreadPool {
public:
    ThreadPool(size_t numThreads) : stop(false) {
        for (size_t i = 0; i < numThreads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    std::unique_ptr<Task> task;
                    
                    {
                        std::unique_lock<std::mutex> lock(queueMutex);
                        condition.wait(lock, [this] {
                            return stop || !tasks.empty();
                        });
                        
                        if (stop && tasks.empty()) return;
                        
                        task = std::move(tasks.front());
                        tasks.pop();
                    }
                    
                    task->execute();
                }
            });
        }
    }
    
    template<class F>
    void enqueue(F&& f) {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            tasks.emplace(std::forward<F>(f));
        }
        condition.notify_one();
    }
    
    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread& worker : workers) {
            worker.join();
        }
    }

private:
    std::vector<std::thread> workers;
    std::queue<std::unique_ptr<Task>> tasks;
    std::mutex queueMutex;
    std::condition_variable condition;
    bool stop;
};

int main() {
    ThreadPool pool(4);
    
    // 添加任务到线程池
    pool.enqueue(std::make_unique<PrintTask>("任务1"));
    pool.enqueue(std::make_unique<CalculateTask>(5, 3));
    pool.enqueue(std::make_unique<PrintTask>("任务2"));
    pool.enqueue(std::make_unique<CalculateTask>(10, 20));
    
    // 等待所有任务完成
    std::this_thread::sleep_for(std::chrono::seconds(1));
    
    return 0;
}

5. 游戏中的输入处理

#include <iostream>
#include <unordered_map>
#include <functional>
#include <vector>

// 游戏角色
class GameCharacter {
public:
    void jump() { std::cout << "角色跳跃" << std::endl; }
    void fire() { std::cout << "角色开火" << std::endl; }
    void crouch() { std::cout << "角色蹲下" << std::endl; }
    void reload() { std::cout << "角色装弹" << std::endl; }
};

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

// 具体命令
class JumpCommand : public InputCommand {
public:
    void execute(GameCharacter& character) override { character.jump(); }
};

class FireCommand : public InputCommand {
public:
    void execute(GameCharacter& character) override { character.fire(); }
};

class CrouchCommand : public InputCommand {
public:
    void execute(GameCharacter& character) override { character.crouch(); }
};

class ReloadCommand : public InputCommand {
public:
    void execute(GameCharacter& character) override { character.reload(); }
};

// 输入处理器
class InputHandler {
public:
    InputHandler() {
        // 初始化按键绑定
        keyBindings['W'] = std::make_unique<JumpCommand>();
        keyBindings['F'] = std::make_unique<FireCommand>();
        keyBindings['C'] = std::make_unique<CrouchCommand>();
        keyBindings['R'] = std::make_unique<ReloadCommand>();
    }
    
    void handleInput(char key, GameCharacter& character) {
        if (keyBindings.count(key)) {
            keyBindings[key]->execute(character);
        }
    }
    
    void rebindKey(char key, std::unique_ptr<InputCommand> cmd) {
        keyBindings[key] = std::move(cmd);
    }

private:
    std::unordered_map<char, std::unique_ptr<InputCommand>> keyBindings;
};

int main() {
    GameCharacter player;
    InputHandler inputHandler;
    
    // 模拟按键输入
    std::vector<char> inputs = {'W', 'F', 'C', 'R'};
    
    for (char input : inputs) {
        inputHandler.handleInput(input, player);
    }
    
    // 重新绑定按键
    inputHandler.rebindKey('W', std::make_unique<CrouchCommand>());
    std::cout << "\n重新绑定W键后:\n";
    inputHandler.handleInput('W', player);
    
    return 0;
}

命令模式的优势
解耦调用者和接收者:调用者不需要知道接收者的具体细节

支持撤销/重做:可以轻松实现命令的撤销和重做功能

支持事务:可以将多个命令组合成一个复合命令

灵活扩展:可以轻松添加新的命令而不影响现有代码

支持队列和日志:可以实现命令的延迟执行或日志记录

适用场景总结
需要将操作请求者和操作执行者解耦的场景

需要支持撤销/重做功能的系统

需要将操作记录日志或支持事务的系统

需要支持宏命令(组合命令)的场景

需要实现回调机制的场景

命令模式通过将请求封装为对象,提供了极大的灵活性和可扩展性,是许多复杂系统设计中不可或缺的模式之一。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值