命令模式是一种行为设计模式,它将请求封装为对象,从而使你可以参数化客户端对象,对请求排队或记录请求日志,以及支持可撤销的操作。
命令模式核心结构
命令模式包含以下主要角色:
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;
}
命令模式的优势
解耦调用者和接收者:调用者不需要知道接收者的具体细节
支持撤销/重做:可以轻松实现命令的撤销和重做功能
支持事务:可以将多个命令组合成一个复合命令
灵活扩展:可以轻松添加新的命令而不影响现有代码
支持队列和日志:可以实现命令的延迟执行或日志记录
适用场景总结
需要将操作请求者和操作执行者解耦的场景
需要支持撤销/重做功能的系统
需要将操作记录日志或支持事务的系统
需要支持宏命令(组合命令)的场景
需要实现回调机制的场景
命令模式通过将请求封装为对象,提供了极大的灵活性和可扩展性,是许多复杂系统设计中不可或缺的模式之一。

325

被折叠的 条评论
为什么被折叠?



