design_patterns/15_command.cpp
Yuki 18694cf41f
feat: Command
Implemented a demo for the Command.
2025-05-15 02:40:27 +08:00

107 lines
2.1 KiB
C++

#include <iostream>
#include <memory>
#include <vector>
using namespace std;
// The interface for communication between back and front
class Command {
public:
virtual bool execute() = 0;
virtual void undo() = 0;
};
// Reciever, which is a backend
class Light {
int status;
public:
Light() : status(0) {}
bool on() {
if (status == 0) {
status = 1;
cout << "Light on" << endl;
return true;
} else {
cout << "Light is already on" << endl;
return false;
}
}
bool off() {
if (status == 1) {
status = 0;
cout << "Light off" << endl;
return true;
} else {
cout << "Light is already off" << endl;
return false;
}
}
int get_status() {
return status;
}
};
class OffCommand : public Command {
shared_ptr<Light> l;
public:
OffCommand(shared_ptr<Light> l) : l(l) {}
bool execute() override {
return l->off();
}
void undo() override {
l->on();
}
};
class OnCommand : public Command {
shared_ptr<Light> l;
public:
OnCommand(shared_ptr<Light> l) : l(l) {}
bool execute() override {
return l->on();
}
void undo() override {
l->off();
}
};
// The Invoker: manages and executes all commands.
// Any class that wants to operate the light can do so by simply
// executing a command, without needing to know the internal details
// of how the light works.
class RemoteControl {
vector<shared_ptr<Command>> cmds;
public:
RemoteControl() {}
void exec_command(shared_ptr<Command> cmd) {
if (cmd->execute()) {
cmds.push_back(cmd);
}
}
void undo() {
if (cmds.size() != 0) {
cmds[cmds.size() - 1]->undo();
cmds.pop_back();
}
}
};
int main() {
auto l = make_shared<Light>();
auto c1 = make_shared<OnCommand>(l);
auto c2 = make_shared<OffCommand>(l);
RemoteControl rc;
rc.exec_command(c1);
rc.exec_command(c1);
rc.exec_command(c2);
rc.undo();
}