c++设计模式概述之命令
代码写的不够规范,目的是为了缩短文章篇幅,实际中请不要这样做。
1、概述
命令模式是一种数据驱动的模式。将请求封装到命令的对象中,再传给调用对象,调用对象再处理该命令。
【将一个请求封装为一个对象】
顺序就是:调用者-> 命令-> 接收者。 故需要定义3个角色: 1、命令的真正执行对象,2、具体的命令,3、invoker,也就是i请求者。
好处: 因为模型已经定下来,所以,额外增加一条命令会轻松许多,但是(缺点)很明显,命令多了,系统慢慢就复杂了 。
类比生活中的场景: 键盘按键,还有界面控件。
下面以买卖商品为例:
2、一个抽象命令的类
// 创建一个命令接口 class oct_cmd { public: virtual void execute() = 0; };
3、invoker, 请求者
// invoker, 将请求封装为一个类, class oct_invoker { public: oct_invoker() : name(std::string("apple")), quantity(10) {} void buy() { std::cout << "\ninvoker [name = " << name.c_str() << "], [quantity=" << quantity << "] bought \n"; } void sell() { std::cout << "\ninvoker [name = " << name.c_str() << "], [quantity=" << quantity << "] sold \n"; } private: std::string name; int quantity; };
4、命令A, 执行购买,继承上面的命令
// 命令A,执行购买, 请求可能有多个,这里就有2个指令,分别对应请求中的接口 class oct_cmd_buy : public oct_cmd { public: // 初始化请求者 void init_invoker(const oct_invoker& instance) { _invoker = instance; } // 重写父类,执行请求者buy的命令 void execute() { _invoker.buy(); } private: // 请求者 oct_invoker _invoker; };
5、命令B执行销售,
// 命令B,执行售卖 class oct_cmd_sell : public oct_cmd { // 初始化请求者 void init_invoker(const oct_invoker& instance) { _invoker = instance; } // 重写父类,执行请求者buy的命令 void execute() { _invoker.sell(); } private: // 请求者 oct_invoker _invoker; };
6、命令调用类
// 创建命令调用类 class oct_call_cmd { public: // 添加命令, void init_cmd(oct_cmd *pcmd) { if (pcmd) _arr_cmd.push_back(pcmd); } // 执行命令 void carry_out_cmd() { for each (auto item in _arr_cmd) item->execute(); // 释放空间 clear_vector<oct_cmd *>(_arr_cmd); } private: // 可能有很多命令 std::vector<oct_cmd *> _arr_cmd; };
7、调用
1 void call_command() 2 { 3 oct_invoker invoker_cmd; 4 std::unique_ptr<oct_cmd> pcmd_sell(new(std::nothrow) oct_cmd_sell); 5 std::unique_ptr<oct_cmd> pcmd_buy(new(std::nothrow) oct_cmd_buy); 6 std::unique_ptr<oct_call_cmd> pcall_cmd(new(std::nothrow) oct_call_cmd); 7 8 if (!pcmd_buy || !pcmd_buy || !pcall_cmd) 9 { 10 std::cout << "\n命令 sell 和 命令 buy 创建失败\n"; 11 return; 12 } 13 14 15 // 添加命令 16 pcall_cmd->init_cmd(pcmd_sell.get()); 17 pcall_cmd->init_cmd(pcmd_buy.get()); 18 19 // 执行命令 20 pcall_cmd->carry_out_cmd(); 21 }
8、输出结果