设计模式之命令模式(Command)

时间:2021-08-30 08:10:04

      命令模式(Command)把请求封装成一个对象,使请求能够存储更多的信息拥有更多的能力。命令模式同样能够把请求的发送者和接收者解耦,但它不关心请求将以何种方式被处理。命令模式经常与职责链模式(Chain of Responsibility)和组合模式(Composite)一起使用:职责链模式处理命令模式封装的对象,组合模式可以把简单的命令对象组合成复杂的命令对象。

      本文举了一个在饭店点菜的例子。(1)烤肉师傅负责在后台(厨房)做饭。(2)Command负责提供提供各种命令,相当于菜单。(3)服务员与客服打交道,负责记录客户点了哪些菜(把客户的命令记下来),然后交给厨师去做。(4)客户就负责点菜。

代码:

#include <iostream>
#include <vector>
#include <string>
using namespace std;


class Command;
class MakeChikenCmd;
class MakeMuttonCmd;
//烤肉师傅
class RoastCook{
friend class MakeChikenCmd;
friend class MakeMuttonCmd;
private:
void MakeMutton()
{ cout << "烤羊肉"; }
void MakeChickenWing()
{ cout << "烤鸡翅膀"; }
};

//命令的接口,抽象类
class Command{
public:
Command(RoastCook* cook)
{
cooker = cook;
}
virtual ~Command(){}
virtual void Execute()=0;
protected:
RoastCook *cooker;//包含了烤肉师傅的对象
};

//烤羊肉命令
class MakeMuttonCmd : public Command{
public:
MakeMuttonCmd(RoastCook *cook):Command(cook){}
void Execute()
{
cooker->MakeMutton();
}
};
//烤鸡肉命令
class MakeChikenCmd : public Command{
public:
MakeChikenCmd(RoastCook *cook):Command(cook){}
void Execute()
{
cooker->MakeChickenWing();
}
};

//服务员类,负责与客服交互
class Waiter{
public:
Waiter(string _name)
{this->name = _name;}
void AddOder(Command* subOder)//加入客户点的菜
{
oder.push_back(subOder);
}

void Notify()
{
vector<Command*>::iterator iter;
cout<<name<<" 通知烤肉师傅请做:"<<endl;
for(iter = oder.begin();iter!=oder.end();++iter){
cout<<" ";
(*iter)->Execute();
cout<<endl;
}
}

string getName()const
{return name;}
private:
vector<Command*> oder;//点菜单
string name;//服务员名字
};

class Custmer{
public:
Custmer(string myname)
{
this->name = myname;
this->w = NULL;
}

void CustmerOder(Command *cmd)
{
cout<<"顾客"<<name<<"点菜"<<endl;
w->AddOder(cmd);
}

void CallWaiter(Waiter *_w)
{
cout<<"顾客"<<name<<"呼叫服务员"<<endl;
this->w = _w;
cout<<"服务员"<<w->getName()<<"为您服务"<<endl;
}
private:
string name;
Waiter *w;
};

int main()
{
RoastCook *cooker = new RoastCook();
Command *cmd = new MakeChikenCmd(cooker);
Command *cmd1 = new MakeMuttonCmd(cooker);

Waiter waiter("sps");
Custmer cust("lsj");
cust.CallWaiter(&waiter);//呼叫服务员

cust.CustmerOder(cmd);//点菜
cust.CustmerOder(cmd1);//点菜

waiter.Notify();//服务员通知后台

system("pause");
return 0;
}