命令模式将一个请求封装为一个对象,从而可用不一样的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操做。ios
命令模式把请求一个操做的对象与知道怎么执行一个操做的对象分割开。编程
命令模式关键就是将一个请求封装到一个类中(Command),再提供处理对象(Receiver),最后Command命令由Invoker激活。另外,能够将请求接收者的处理抽象出来做为参数传给Command对象,实际也就是回调的机制来实现这一点。将处理操做方法地址经过参数传递给Command对象,Command对象在适当的时候再调用该函数。设计模式
命令模式将调用操做的对象和知道如何实现操做的对象解耦,Invoker对象根本不知道具体的是哪一个对象在处理Execute操做(固然要知道是Command类别的对象)。
在Command要增长新的处理操做对象很容易,能够经过建立新的继承自Command的子类来实现这一点。
命令模式能够和备忘录模式结合起来,支持取消的操做。ide
命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开。每个命令都是一个操做:请求的一方发出请求,要求执行一个操做;接收的一方收到请求,并执行操做。命令模式容许请求的一方和接收的一方独立开来,使得请求的一方没必要知道接收请求的一方的接口,更没必要知道请求是怎么被接收,以及操做是否被执行、什么时候被执行,以及是怎么被执行的。命令模式使请求自己成为一个对象,这个对象和其余对象同样能够被存储和传递。命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。函数
接收者(Receiver): 知道如何实施与执行一个请求相关的操做。任何类均可能做为一个接收者,只要可以实现命令要求实现的相应功能。ui
抽象命令类(Command): 用于声明执行操做的接口。spa
具体命令类(ConcreteCommand): 建立一个具体命令对象并设定其接收者。一般会持有接收者,并调用接收者的功能来完成命令要执行的操做。 将一个接收者对象绑定于一个操做,调用接收者相应的操做,以实现Execute。设计
调用者(Invoker): 要求命令执行这个请求。一般会持有命令对象,能够持有多个命令对象。 日志
客户类(Client): 建立具体的命令对象,而且设置命令对象的接收者。真正使用命令的客户端是从Invoker来触发执行。 对象
命令模式经过将请求封装到一个对象Command中,并将请求的接收者存放到具体的ConcreteCommand类中,从而实现调用操做的对象和操做的具体实现者之间的解耦。
命令模式结构图中,将请求的接收者(处理者)放到Command的具体子类ConcreteCommand中,当请求到来时(Invoker发出Invoke消息激活Command对象),ConcreteCommand将处理请求交给Receiver对象进行处理。
命令模式的优势:
A、可将多个命令装配成一个组合命令,能较容易地设计一个命令队列。
B、在须要的状况下,能够较容易地将命令记入日志。
C、容许接收请求的一方决定是否要否决请求。
D、能够容易地实现对请求的撤销和重作。
E、增长新的具体命令类很容易,由于加进新的具体命令类不影响其余的类
F、下降系统的耦合度:Command模式将调用操做的对象与知道如何实现该操做的对象解耦。
命令模式的缺点:
使用命令模式可能会致使某些系统有过多的具体命令类。由于针对每个命令都须要设计一个具体命令类,所以某些系统可能须要大量具体命令类,影响命令模式的使用。
命令模式使用场景:
A、系统须要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
B、系统须要在不一样的时间指定请求、将请求排队和执行请求。
C、系统须要支持命令的撤销(Undo)操做和恢复(Redo)操做。
D、系统须要将一组操做组合在一块儿,即支持宏命令。
Invoker调用者类:
#ifndef INVOKER_H #define INVOKER_H #include "Command.h" class Invoker { public: //装载具体的命令对象 void setCommand(Command *com) { m_pCom = com; } void Invoke() { //执行持有的命令 m_pCom->Execute(); } private: Command* m_pCom; }; #endif // INVOKER_H
Command抽象命令类:
#ifndef COMMAND_H #define COMMAND_H #include "Receiver.h" //命令抽象类 class Command { public: //命令执行接口 virtual void Execute() = 0; protected: Command(){} }; #endif // COMMAND_H
ConcreteCommandA具体命令类:
#ifndef CONCRETECOMMANDA_H #define CONCRETECOMMANDA_H #include "Command.h" #include "Receiver.h" //具体命令类 class ConcreteCommandA : public Command { public: //具体命令对象并设定其接收者 ConcreteCommandA(Receiver* pReceiver) { m_pReceiver = pReceiver; } void Execute() { //执行接收者绑定的操做 m_pReceiver->Action(); } private: Receiver* m_pReceiver; }; #endif // CONCRETECOMMANDA_H
ConcreteCommandB具体命令类:
#ifndef CONCRETECOMMANDB_H #define CONCRETECOMMANDB_H #include "Command.h" #include "Receiver.h" //具体命令类 class ConcreteCommandB : public Command { public: //具体命令对象并设定其接收者 ConcreteCommandB(Receiver* pReceiver) { m_pReceiver = pReceiver; } void Execute() { //执行接收者绑定的操做 m_pReceiver->Action(); } private: Receiver* m_pReceiver; }; #endif // CONCRETECOMMANDB_H
Receiver接收者类:
#ifndef RECEIVER_H #define RECEIVER_H #include <iostream> using namespace std; //接收者 class Receiver { public: //请求实际执行的操做 void Action() { cout << "Receiver::Action()" << endl; } }; #endif // RECEIVER_H
客户调用程序:
#include "Command.h" #include "ConcreteCommandA.h" #include "ConcreteCommandB.h" #include "Receiver.h" #include "Invoker.h" int main() { //建立命令的接收者 Receiver* pReceiver = new Receiver(); //指定命令的接收者建立命令 Command* pCom = new ConcreteCommandA(pReceiver); //建立请求者 Invoker* pInvoker = new Invoker(); //设置调用的命令 pInvoker->setCommand(pCom); pInvoker->Invoke();//执行命令 delete pReceiver; delete pCom; delete pInvoker; return 0; }
餐厅业务流程中,经过服务员来点菜,顾客产生订单请求,订单中具体是哪位厨师作菜顾客并不知道。顾客是“菜单请求者”,厨师是“菜单实现者”,产生的菜单订单即命令对象,服务员可能会接到多个订单,并将订单分配给厨师,厨师根据接到的菜单作菜。餐厅只提供川菜和粤菜两种菜系选择。
Command抽象类:
#ifndef COMMAND_H #define COMMAND_H #include <iostream> #include <string> #include "Master.h" using namespace std; //Command抽象类,订单 class Command { public: //命令对象通知Receiver的接口 virtual void cooking() = 0; protected: Command(Master* master) { m_pMaster = master; } protected: Master* m_pMaster; }; #endif // COMMAND_H
CantoneseCuisine粤菜订单类:
#ifndef CANTONESECUISINE_H #define CANTONESECUISINE_H #include "Command.h" //具体Command,粤菜订单 class CantoneseCuisine : public Command { public: CantoneseCuisine(Master* master):Command(master) {} //通知厨师接到新的粤菜订单 void cooking() { cout << "CantoneseCuisineMaster: an new CantoneseCuisine order" << endl; //厨师作菜 m_pMaster->doAction(); } }; #endif // CANTONESECUISINE_H
SiChuanFood川菜订单类:
#ifndef SICHUANFOOD_H #define SICHUANFOOD_H #include "Command.h" //具体Command,川菜订单 class SiChuanFood : public Command { public: SiChuanFood(Master* master):Command(master) {} //通知厨师接到新的川菜订单 void cooking() { cout << "SiChuanFoodMaster: an new SiChuanFood order" << endl; //厨师作菜 m_pMaster->doAction(); } }; #endif // SICHUANFOOD_H
Master厨师抽象类:
#ifndef MASTER_H #define MASTER_H #include <iostream> using namespace std; //Receiver抽象类,厨师 class Master { public: virtual void doAction() = 0; protected: Master(){} }; #endif // MASTER_H
CantoneseCuisineMaster粤菜厨师类:
#ifndef CANTONESECUISINEMASTER_H #define CANTONESECUISINEMASTER_H #include "Master.h" //Receiver具体实现类,粤菜厨师 class CantoneseCuisineMaster : public Master { public: //粤菜厨师作菜 void doAction() { cout << "CantoneseCuisineMaster is cooking" << endl; } }; #endif // CANTONESECUISINEMASTER_H
SiChuanFoodMaster川菜厨师类:
#ifndef SICHUANFOODMASTER_H #define SICHUANFOODMASTER_H #include "Master.h" //Receiver具体实现类,川菜厨师 class SiChuanFoodMaster : public Master { public: //川菜厨师作菜 void doAction() { cout << "SiChuanFoodMaster is cooking" << endl; } }; #endif // SICHUANFOODMASTER_H
Waiter服务员类:
#include <ctime> #include <typeinfo> #include "Command.h" #include "SiChuanFood.h" #include "CantoneseCuisine.h" using namespace std; //Invoker类,服务员 class Waiter { public: Waiter() { m_commands = new vector<Command*>; } ~Waiter() { delete m_commands; } //装载订单到订单池 void setOrder(Command* command) { time_t now=time(0); //判断订单的类型并分别作不一样的处理 if(typeid(*command) == typeid(SiChuanFood)) { //川菜 cout<<"plog: Waiter receive an new order. Cuisine: " << typeid(*command).name()<<" Time:" << asctime(gmtime(&now)); m_commands->push_back(command); } else if(typeid(*command) == typeid(CantoneseCuisine)) { //粤菜 m_commands->push_back(command); cout<<"plog: Waiter receive an new order. Cuisine: " << typeid(*command).name()<<" Time:" << asctime(gmtime(&now)); } else { //没有提供其余菜系 cout << "plog: Waiter: No service at now" << endl; } } //通知厨师作菜 void notify() { vector<Command*>::iterator iter; for(iter = m_commands->begin(); iter != m_commands->end(); ++iter) (*iter)->cooking(); } protected: vector<Command*>* m_commands;//订单对象池 }; #endif // WAITER_H
客户调用程序:
#include "Master.h" #include "CantoneseCuisineMaster.h" #include "SiChuanFoodMaster.h" #include "Command.h" #include "CantoneseCuisine.h" #include "SiChuanFood.h" #include "Waiter.h" int main() { //生成川菜厨师 Master* siChuanFoodMaster = new SiChuanFoodMaster(); //生成粤菜厨师 Master* cantoneseCuisineMaster = new CantoneseCuisineMaster(); //顾客产生川菜订单 Command* siChuanFood = new SiChuanFood(siChuanFoodMaster); //顾客产生粤菜订单 Command* cantoneseCuisine = new CantoneseCuisine(cantoneseCuisineMaster); //生成服务员 Waiter* waiter = new Waiter(); //将顾客订单对象推送到订单队列 waiter->setOrder(siChuanFood); waiter->setOrder(cantoneseCuisine); //服务员通知厨师已经接到的需求订单 waiter->notify(); delete siChuanFoodMaster,cantoneseCuisineMaster; delete siChuanFood,cantoneseCuisine,waiter; return 0; }