命令模式在 C++ 代码中很常见,大部分情况下, 它被用于代替包含行为的参数化 UI 元素的回调函数。我不知道你是否阅读过任意网络库,这边就以 Muduo 网络库举例说明:
用户传递的 某个回调函数(往往是读操作和写操作)通过层层传递,最终会被 Channel 这个调用者执行,但是用户不必关心谁来执行这个回调函数(即用户发出的命令),只需要发出命令即可。可以看出,用户发出的命令会被存储起来,实际的执行也不是由 TcpServer 执行。
因此,我们讲命令模式可以对发送者和接收者(执行者)完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #include <iostream> #include <map> #include <list> using namespace std;
class Command { public: virtual string name() = 0; virtual void Excute() = 0; virtual ~Command(){} };
class Invoker { public: void makeGBJD() { cout << "制作 宫保鸡丁" << endl; }
void makeCQXM() { cout << "制作 重庆小面" << endl; }
void makeMCKR() { cout << "制作 梅菜扣肉" << endl; } };
class GBJDCommand : public Command { public: GBJDCommand(Invoker* inv) :invoker_(inv){} void Excute() override { invoker_->makeGBJD(); } string name() override { return "GBJD"; } virtual ~GBJDCommand() {}; protected: Invoker* invoker_; };
class CQXMCommand : public Command { public: CQXMCommand(Invoker* inv) :invoker_(inv) {} void Excute() override { invoker_->makeCQXM(); } string name() override { return "CQXM"; } virtual ~CQXMCommand() {}; protected: Invoker* invoker_; };
class MCKRCommand : public Command { public: MCKRCommand(Invoker* inv) :invoker_(inv) {} void Excute() override { invoker_->makeMCKR(); } string name() override { return "MCKR"; } virtual ~MCKRCommand() {}; protected: Invoker* invoker_; };
class Transmitter { public: void give_order(int uuid,Command* command) { cout << "uuid = " << uuid << "| 下达命令 = " << command->name() <<endl;
auto its = orders_.find(uuid); if (its != orders_.end()) { orders_[uuid].push_back(command); } else { list<Command*> data = { command }; orders_[uuid] = data; }
} void cancel_order(int uuid, Command* command) { auto its = orders_.find(uuid); if (its != orders_.end()) { cout << "uuid = " << uuid << "| 取消命令 = " << command->name() << endl; orders_[uuid].remove(command); } }
void submit_order() { for (auto order : orders_) { for (auto conmand : order.second) { conmand->Excute(); } } orders_.clear(); }
private: map<int, list<Command*>> orders_; };
|
客户端测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| int main(int argc,char* argv[]) {
Invoker* invoker = new Invoker(); Transmitter* trans = new Transmitter();
GBJDCommand* gbjd = new GBJDCommand(invoker); CQXMCommand* cqxm = new CQXMCommand(invoker); MCKRCommand* mkqr = new MCKRCommand(invoker);
trans->give_order(1, gbjd); trans->give_order(1, mkqr); trans->cancel_order(1, mkqr); trans->submit_order();
trans->give_order(2, cqxm); trans->give_order(2, gbjd); trans->give_order(2, mkqr); trans->cancel_order(2, gbjd); trans->submit_order();
return 0; }
|
想必各位也看出来了,如果我们需要更多的命令,那就需要添加更多的命令类,同时还要在 Invoker 类中添加实际的执行代码。