【设计模式】烤羊肉串引来的思考 --- 命令模式
一,概述
定义:命令模式将一个请求或者操作封装到一个命令对象中。允许系统使用不同的请求将客户端参数化,对请求排队或者记录请求日志,提供命令的撤销,恢复能力
优点:
1 命令模式使新的命令很容易被加入
2 允许接受请求方否决请求
3 可较容易地设计一个命令队列
4 可以实现对请求的Undo,Redo
5 可以将命令计入日志
二,示例
两个人 去吃烧烤,先路过一个烧烤摊,人多管理比较混乱,命令请求者跟命令实施者“紧耦合”。
人太对,没吃,然后去烧烤店,遇到了经典的命令模式:服务生负责记录命令,传递命令。厨师负责执行命令。顾客则发出命令
1)烧烤摊代码
#include <iostream> using namespace std; //烤肉串者 class Barbecuer { //烤羊肉 public: void BakeMutton() { cout<<"烤羊肉串!"<<endl; } //烤鸡翅 void BakeChickenWing() { cout<<"烤鸡翅!"<<endl; } }; int main() { Barbecuer *boy = new Barbecuer(); boy->BakeMutton(); boy->BakeMutton(); boy->BakeMutton(); boy->BakeChickenWing(); boy->BakeMutton(); boy->BakeMutton(); boy->BakeChickenWing(); }
2)烧烤店(第一版)
缺点:客户点一个菜,服务员通知一下(不符合实际)。应该点菜完成后一次性通知
如果某一个菜没有了,不应该客户判断,应该服务员判断
客户点菜需要记录日志,以备结账使用。
#include <iostream> using namespace std; //烤肉串者 class Barbecuer//命令执行者 { public: void BakeMutton() { cout<<"烤羊肉串!"<<endl; } void BakeChickenWing() { cout<<"烤鸡翅!"<<endl; } }; //抽象命令 class Command//声明执行的接口 { protected: Barbecuer *receiver; public: Command(Barbecuer *receiver) { this->receiver = receiver; } //执行命令 virtual void ExcuteCommand()=0; }; //服务员 class Waiter //Invoker类 { private: Command *command; //设置订单 public: void SetOrder(Command *command) { this->command = command; } //通知执行 void Notify() { command->ExcuteCommand(); } }; //烤羊肉串命令 class BakeMuttonCommand :public Command { public: BakeMuttonCommand(Barbecuer *receiver) : Command(receiver) { } void ExcuteCommand() { receiver->BakeMutton(); } }; //烤鸡翅命令 class BakeChickenWingCommand :public Command { public: BakeChickenWingCommand(Barbecuer *receiver) : Command(receiver) { } void ExcuteCommand() { receiver->BakeChickenWing(); } }; int main() { //开店前的准备 Barbecuer *boy = new Barbecuer(); Command *bakeMuttonCommand1 = new BakeMuttonCommand(boy);// 烤羊肉 Command *bakeMuttonCommand2 = new BakeMuttonCommand(boy); Command *bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);//烤鸡翅 Waiter *girl = new Waiter(); //开门营业 girl->SetOrder(bakeMuttonCommand1); girl->Notify(); girl->SetOrder(bakeMuttonCommand2); girl->Notify(); girl->SetOrder(bakeChickenWingCommand1); girl->Notify(); }
3)烧烤店(松耦合升级版)(C#)
static void Main(string[] args) { //开店前的准备 Barbecuer boy = new Barbecuer(); Command bakeMuttonCommand1 = new BakeMuttonCommand(boy); Command bakeMuttonCommand2 = new BakeMuttonCommand(boy); Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy); Waiter girl = new Waiter(); //开门营业 顾客点菜 girl.SetOrder(bakeMuttonCommand1); girl.SetOrder(bakeMuttonCommand2); girl.SetOrder(bakeChickenWingCommand1); //点菜完闭,通知厨房 girl.Notify(); Console.Read(); } } //服务员 public class Waiter { private IList<Command> orders = new List<Command>(); //设置订单 public void SetOrder(Command command) { if (command.ToString() == "命令模式.BakeChickenWingCommand") { Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤。"); } else { orders.Add(command); Console.WriteLine("增加订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString()); } } //取消订单 public void CancelOrder(Command command) { orders.Remove(command); Console.WriteLine("取消订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString()); } //通知全部执行 public void Notify() { foreach (Command cmd in orders) { cmd.ExcuteCommand(); } } } //抽象命令 public abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) { this.receiver = receiver; } //执行命令 abstract public void ExcuteCommand(); } //烤羊肉串命令 class BakeMuttonCommand : Command { public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { } public override void ExcuteCommand() { receiver.BakeMutton(); } } //烤鸡翅命令 class BakeChickenWingCommand : Command { public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) { } public override void ExcuteCommand() { receiver.BakeChickenWing(); } } //烤肉串者 public class Barbecuer { public void BakeMutton() { Console.WriteLine("烤羊肉串!"); } public void BakeChickenWing() { Console.WriteLine("烤鸡翅!"); } }
三,命令模式基本代码构成
#include <iostream> using namespace std; class Receiver//执行命令类 { public: void Action() { cout<<"执行请求!"<<endl; } }; class Command //声明执行操作的接口 { protected: Receiver *receiver; public: Command(Receiver *receiver) { this->receiver = receiver; } virtual void Execute()=0; }; class Invoker//要求该命令执行这个请求 { private: Command *command; public: void SetCommand(Command *command) { this->command = command; } void ExecuteCommand() { command->Execute(); } }; class ConcreteCommand :public Command //将一个接收者对象绑定于一个动作 { public: ConcreteCommand(Receiver *receiver):Command(receiver) { } void Execute() //实现命令接口 { receiver->Action(); } }; int main() { Receiver *r = new Receiver();//命令的真正执行类 (后台厨师) Command *c = new ConcreteCommand(r);//将命令绑定到 命令执行者 (顾客) Invoker *i = new Invoker();//要求命令执行者执行命令(记账单的小生) // Set and execute command i->SetCommand(c); i->ExecuteCommand(); system("pause"); }