C++命令模式与请求封装
C++命令模式与请求封装
命令模式将请求封装为对象,支持参数化、队列化和可撤销操作。这是实现撤销/重做、事务和任务调度的基础。
命令接口定义execute方法。
#include
#include
#include
#include
#include
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
virtual void undo() = 0;
virtual std::string name() const = 0;
};
class Light {
public:
void on() { std::cout << "Light ON\n"; }
void off() { std::cout << "Light OFF\n"; }
};
class LightOnCommand : public Command {
Light& light_;
public:
explicit LightOnCommand(Light& l) : light_(l) {}
void execute() override { light_.on(); }
void undo() override { light_.off(); }
std::string name() const override { return "Light On"; }
};
class LightOffCommand : public Command {
Light& light_;
public:
explicit LightOffCommand(Light& l) : light_(l) {}
void execute() override { light_.off(); }
void undo() override { light_.on(); }
std::string name() const override { return "Light Off"; }
};
class Fan {
int speed_ = 0;
public:
void high() { speed_ = 3; std::cout << "Fan HIGH\n"; }
void medium() { speed_ = 2; std::cout << "Fan MEDIUM\n"; }
void low() { speed_ = 1; std::cout << "Fan LOW\n"; }
void off() { speed_ = 0; std::cout << "Fan OFF\n"; }
int speed() const { return speed_; }
};
class FanCommand : public Command {
Fan& fan_;
int prev_speed_;
int new_speed_;
std::string name_;
public:
FanCommand(Fan& f, int speed, const std::string& n)
: fan_(f), new_speed_(speed), name_(n) {}
void execute() override {
prev_speed_ = fan_.speed();
switch (new_speed_) {
case 3: fan_.high(); break;
case 2: fan_.medium(); break;
case 1: fan_.low(); break;
default: fan_.off(); break;
}
}
void undo() override {
switch (prev_speed_) {
case 3: fan_.high(); break;
case 2: fan_.medium(); break;
case 1: fan_.low(); break;
default: fan_.off(); break;
}
}
std::string name() const override { return name_; }
};
class RemoteControl {
std::vector> on_commands_;
std::vector> off_commands_;
std::stack history_;
public:
void set_command(int slot, std::unique_ptr on, std::unique_ptr off) {
if (slot >= on_commands_.size()) {
on_commands_.resize(slot + 1);
off_commands_.resize(slot + 1);
}
on_commands_[slot] = std::move(on);
off_commands_[slot] = std::move(off);
}
void on_button(int slot) {
if (slot < on_commands_.size() && on_commands_[slot]) {
on_commands_[slot]->execute();
history_.push(on_commands_[slot].get());
}
}
void off_button(int slot) {
if (slot < off_commands_.size() && off_commands_[slot]) {
off_commands_[slot]->execute();
history_.push(off_commands_[slot].get());
}
}
void undo() {
if (!history_.empty()) {
history_.top()->undo();
history_.pop();
}
}
};
void command_demo() {
Light light;
Fan fan;
RemoteControl remote;
remote.set_command(0,
std::make_unique(light),
std::make_unique(light));
remote.set_command(1,
std::make_unique(fan, 3, "Fan High"),
std::make_unique(fan, 0, "Fan Off"));
remote.on_button(0);
remote.on_button(1);
remote.off_button(0);
remote.undo();
remote.undo();
remote.undo();
}
宏命令组合多个命令。
class MacroCommand : public Command {
std::vector commands_;
public:
void add(Command* cmd) { commands_.push_back(cmd); }
void execute() override {
for (auto* cmd : commands_) cmd->execute();
}
void undo() override {
for (auto it = commands_.rbegin(); it != commands_.rend(); ++it) {
(*it)->undo();
}
}
std::string name() const override { return "Macro"; }
};
函数式命令使用lambda。
class FunctionalCommand : public Command {
std::function execute_;
std::function undo_;
std::string name_;
public:
FunctionalCommand(std::function exec, std::function und,
std::string n)
: execute_(std::move(exec)), undo_(std::move(und)), name_(std::move(n)) {}
void execute() override { execute_(); }
void undo() override { undo_(); }
std::string name() const override { return name_; }
};
void functional_command_demo() {
int value = 0;
int previous = 0;
auto inc = std::make_unique(
[&]() { previous = value; value += 10; std::cout << "Value: " << value << "\n"; },
[&]() { value = previous; std::cout << "Undo: " << value << "\n"; },
"Increment"
);
inc->execute();
inc->execute();
inc->undo();
}
命令模式将调用者与接收者解耦,支持操作排队和撤销。
