feat: Command

Implemented a demo for the Command.
This commit is contained in:
Yuki 2025-05-15 02:40:27 +08:00
parent 6df2c90168
commit 18694cf41f
Signed by: yuki
GPG Key ID: CF40579331C06C73
2 changed files with 114 additions and 0 deletions

106
15_command.cpp Normal file
View File

@ -0,0 +1,106 @@
#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();
}

View File

@ -97,3 +97,11 @@
责任链模式解决了这个问题。一个 handler 要么处理这个请求,要么交给下一个 handler 处理,增加处理逻辑时,只需要新增一个 handler并且正确设置相应的 next 即可。这样,每个 handler 只关心自己的职责,所有 handler 处理清晰。当我们能将所有的 handler 组成一个链式或者树式的结构时,这会非常有用。 责任链模式解决了这个问题。一个 handler 要么处理这个请求,要么交给下一个 handler 处理,增加处理逻辑时,只需要新增一个 handler并且正确设置相应的 next 即可。这样,每个 handler 只关心自己的职责,所有 handler 处理清晰。当我们能将所有的 handler 组成一个链式或者树式的结构时,这会非常有用。
但也正如前面提到的,这不自然支持“一个请求需多个处理者同时处理”的场景。此时可以通过责任链进一步推广成“责任网”,观察者模式,流程引擎式结构等,增强责任链模式的处理能力。 但也正如前面提到的,这不自然支持“一个请求需多个处理者同时处理”的场景。此时可以通过责任链进一步推广成“责任网”,观察者模式,流程引擎式结构等,增强责任链模式的处理能力。
## 命令模式Command
一个系统通常分为前端和后端两部分,前端负责接收用户输入,后端处理核心业务逻辑。那么,前后端之间如何高效、清晰地交互呢?如果每个后端模块都暴露自己的接口,系统一旦扩展,接口之间容易混乱、难以维护。
命令模式通过引入统一的“命令对象”,将请求的发送者(前端)与执行者(后端)解耦。前端只需构造命令并发送,不关心命令的执行细节;而后端根据命令对象来执行相应逻辑。
更重要的是,所有操作都被抽象为统一的命令接口,这使得命令可以统一记录、排队、撤销、重做。多个前端只需绑定相同的命令对象,即可复用相同的后端逻辑,增强了代码复用性与系统扩展性。