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