命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。
命令看成是函数方法,而这函数方法在不同的业务含义中,其参数个数,参数的数据类型,返回值可能不统一。把用户可以触发的功能当成一个命令,把这个“命令”封装成一个对象。把对象抛给接收者,让接收者处理其中的命令。而这个接收者可以接收命令的抽象类。这样接收者就可以间接的统一处理 接口不统一的函数方法了。
以添加商品到购物车,删除购物车中的商品,支付购物车的商品为例:
class ICommand{
public:
virtual void execute() = 0;
};
class Commodity{
public:
string id;
};
class ShoppingCart{
public:
string cartid;
List<Commodity> commodities;
};
//原先添加商品,需要传两个参数 (Commodity,ShoppingCart),现在用对象封装在构造函数和execute中
class AddCommodityToCart :public ICommand{
Commodity commodity ;
ShoppingCart shoppingCart ;
public:
void AddCommodityToCart (Commodity c, ShoppingCart s):commodity(c),shoppingCart (s){}
void execute() {
shoppingCart.commodities.add(commodity );
}
};
//原先删除商品,需要传两个参数 (ShoppingCart,string ),现在用对象封装在构造函数和execute中
class RemoveCommodity :public ICommand{
string commodityId;
ShoppingCart shoppingCart ;
public:
void RemoveCommodity (ShoppingCart s,string c):commodityId(c),shoppingCart (s){}
void execute() {
for(Commodity commodity : shoppingCart.commodities){
if(commodity.id == commodityId){
shoppingCart.commodities.remove(commodity );
}
}
}
};
//原先清空购物车,需要传一个参数 (ShoppingCart),现在用对象封装在构造函数和execute中
class PayCart :public ICommand{
ShoppingCart shoppingCart ;
public:
void PayCart (ShoppingCart s): shoppingCart (s){}
void execute() {
cout<<"购物车支付:";
for(Commodity commodity : shoppingCart.commodities){
cout<<commodity.id <<"\t";
}
shoppingCart.commodities.clear();
}
};
//执行命令的类
class Receiver {
private :
List <ICommand*> commands;
public:
void addCommands(ICommand* c){commands.add(c);};
void action(ICommand* c=nullptr){
if(c !==nullptr)
commands.add(c);
for (int i =0 ;i<commands.size();i++){
commands[i]->execute();
}
}
};
而调用起来也是很方便的
Receiver USER_;
ShoppingCart USERCART_;
void executecommand(Icommand * c){USER.action(c);}
void mainProcess(){
Commodity commodity1("book");
Commodity commodity1("game");
AddCommodityToCart addCommodityToCart(commodity1,USERCART_);
RemoveCommodityToCart removeCommodityToCart(USERCART_,"book");
PayCart paycart(USERCART_);
USER_.addCommand(&addCommodityToCart);
USER_.addCommand(&removeCommodityToCart);
executecommand(&paycart) ;
//输出 购物车支付game;
}
命令模式的实现,让Receiver 对象成功处理 参数类型不同,参数个数不同,返回值不同的多个方法。当然在现如今已有更方便的实现方式可以满足 “接收处理 格式不统一的函数” 。 例如 模板/泛型 ,重载括号运算符(函数对象)等方式实现。毕竟虚函数的运行时绑定(动态绑定)要比编译时绑定的性能要低些。