【设计模式】烤羊肉串引来的思考 --- 命令模式

一,概述

        定义:命令模式将一个请求或者操作封装到一个命令对象中。允许系统使用不同的请求将客户端参数化,对请求排队或者记录请求日志,提供命令的撤销,恢复能力

        优点:

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"); 
} 


posted @ 2012-07-10 16:03  MXi4oyu  阅读(261)  评论(0编辑  收藏  举报