1. 程式人生 > >【設計模式】——命令模式

【設計模式】——命令模式

【命令模式】

命令模式(Command),將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化,對請求進行排隊或者使記錄請求日誌,以及支援可撤銷的操作

【介紹】

  • 主要解決:在軟體系統中,行為請求者與行為實現者通常是一種緊耦合的關係,但是某些場合,需要對行為進行紀錄、撤銷或者重做、事務等處理時候

  • 何時使用:將一組行為先抽象為物件,可以事先二者之間的鬆耦合

  • 如何解決:通過呼叫者呼叫接收者執行命令,順序:呼叫者——接收者——命令

  • 關鍵程式碼:三個角色——received真正的命令執行物件;command;invoker使用命令物件的入口

  • 優點:降低了系統的耦合度、新的命令可以很容易的新增到系統中去

  • 缺點:使用命令模式可能會導致某些系統有過的具體命令類

  • 注意事項:系統需要支援命令的撤銷操作和恢復操作

【實現】

步驟一:抽象命令

public abstract class Command

    {

        protected Barbecuer receiver;

        public Command (Barbecuer receiver)//確定廚師是誰

        {

            this.receiver = receiver;

        }

        //執行命令

        abstract public void ExcuteCommand();

    }

步驟二:具體命令類

class BraisedFishCommand : Command//紅燒魚命令

    {

        public BraisedFishCommand(Barbecuer receiver):base (receiver)

        {



        }

        public override void ExcuteCommand()

        {

            receiver.BraisedFish();

        }

    }

    class YuXiangFishCommand : Command//魚香肉絲命令

    {

        public YuXiangFishCommand(Barbecuer receiver) : base(receiver)

        {



        }

        public override void ExcuteCommand()

        {

            receiver.YuXiangFish();

        }

    }

步驟三:服務員類

 public class Waiter

    {

        private IList<Command> orders= new List<Command >();

        //設定訂單

        public void SetOrder(Command command)

        {

            if (command .ToString () == "命令模式.BraisedFishCommand")

            {

                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 class Barbecuer

    {

        //做紅燒魚

        public void BraisedFish()

        {

            Console.WriteLine("做紅燒魚");

        }

        //做魚香肉絲

        public void YuXiangFish()

        {

            Console.WriteLine("做魚香肉絲");

        }



    }

步驟五:客戶端程式碼

 static void Main(string[] args)

        {

            //開店前的準備

            Barbecuer boy = new Barbecuer();

            Command BraisedFishCommand1 = new BraisedFishCommand(boy);

            Command BraisedFishCommand2 = new BraisedFishCommand(boy);

            Command YuXiangFishCommand1 = new YuXiangFishCommand(boy);

         

            Waiter girl = new Waiter();

            //門店事先找好廚師和服務員



            //開門營業

            girl.SetOrder(BraisedFishCommand1);

           

            girl.SetOrder(YuXiangFishCommand1);

          

            girl.SetOrder(BraisedFishCommand2);

            girl.Notify();

            Console.Read();



        }



【總結】

一、命令模式的優點

  • 能比較容易的設計一個命令佇列

  • 在需要的情況下,可以比較容易的將命令記入日誌

  • 允許接受請求的一方決定是否要否決請求

  • 可以容易的實現對請求的撤銷和重做

  • 新增新的具體命令類不影響其他的類,增加新的具體命令類很容易

  • 命令模式把請求一個操作的物件與指導怎麼執行一個操作的物件分割開

二、敏捷開發原則:不要為程式碼新增基於猜測的、實際不需要的功能。如果不清楚一個系統是否需要命令模式,一般就不要著急去實現它,事實上,需要的時候通過重構實現這個模式並不困難,只有在真正需要如撤銷和恢復操作等功能時,把原來的程式碼重構為命令模式才有意義。