命令模式

来源:互联网 发布:淘宝详情页切图大小 编辑:程序博客网 时间:2024/05/21 04:25
       想象一个场景,你是一个烧烤店的老板,卖烤鸡翅考羊肉,来了一群客人来点菜,模式一,直接给烧烤师傅发命令让他考鸡翅和烤羊肉,这样做简单粗暴,但是问题来了一旦人一多,师傅就很容易出错。实际上,一个店里都有一个服务员,客人都是直接问服务员,然后服务员给师傅发命令,这样做,提高了效率,师傅只负责烧烤,不负责其他的。很容易发现,第二种发出命令(服务员)和执行命令(执行命令)的责任分开。

       命令模式,将一个请求封装成一个对象,从而是你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销操作。


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();//服务员去叫烧烤师傅}


原创粉丝点击