命令模式,将一个请求封装成一个对象,从而是你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销操作。
Comman提供执行命令接口,ConcreteCommand类,调用接受者执行响应的操作,比如程序里的烤羊肉烤鸡翅操作,Receviver类是一个执行命令的集合,比如上面的烤肉师傅,命令的真正执行者,Invoker,发出命令执行,就相当于那个服务员。
命令模式本质:对命令进行封装,将发出命令与执行命令责任分开。
命令模式优点:它比较容易地设计一个命令队列,比如程序里list<Command*>命令队列;在需要的情况下,比较容易将命令写入日志;允许接收请求的一方决定是否要否决请求,比如客人来点烤羊肉,客人不需要知道羊肉够不够,由服务员来决定;可以很容地实现对请求的撤销和重做;加进新的具体命令类不影响其他的类,因此增加新的具体命令很容易。
缺点:因为针对每一个命令都需要设计一个具体命令类,使用命令模式可能会导致系统有过多的具体命令类。
使用场景: 1. 需要对记录进行“记录、撤销、重做”等处理。
2. 需要将请求者和接收者解耦,是的调用者和接收者不直接交互。
3. 系统需要在不同时间指定请求、请求排队和执行请求。
4. 系统需要将一组操作组合在一起。
#include<iostream> #include<list> #include<string> using namespace std; class Barbecuer//烧烤师傅,负责烧烤 { public: void bakeMutton() { cout << "烤羊肉" << endl; } void bakeChick() { cout << "烤鸡翅" << endl; } }; class Command// { protected: Barbecuer *receiver;//命令的接收者,执行命令的人 public: Command(Barbecuer *b) :receiver(b) {} virtual void excutecommand() = 0;//执行命令 }; class BakeMuttonCommad :public Command//执行烤羊肉命令 { public: BakeMuttonCommad(Barbecuer *barbecuer) :Command(barbecuer) {} void excutecommand() { receiver->bakeMutton(); } }; class BakeChikenCommand :public Command//执行烤鸡翅命令 { public: BakeChikenCommand(Barbecuer *barbecuer) :Command(barbecuer) {} void excutecommand() { receiver->bakeChick(); } }; class Waiter { private: list<Command*>orders;//因为客人要源源不断的来,所以要用list来保存命令; public: void addOrder(Command* command)//添加命令 { orders.push_back(command); } void notify()//通知,发出命令 { list<Command*>::iterator p = orders.begin(); for (; p != orders.end(); p++) { (*p)->excutecommand();//发出命令 } } }; int main() { Waiter w;//首先得有一个服务员 Barbecuer *boy = new Barbecuer();//得有一个烧烤师傅 Command *cm1 = new BakeChikenCommand(boy);//来了三个人所以有三个命令 Command *cm2 = new BakeMuttonCommad(boy); Command *cm3 = new BakeChikenCommand(boy); w.addOrder(cm1);//需要把三个命令发给服务员 w.addOrder(cm2); w.addOrder(cm3); w.notify();//服务员去叫烧烤师傅 }