C#設計模式之命令模式

提高班14期郭倩_Ulrica發表於2018-06-05

前言

由於上一篇部落格備忘錄模式提到了命令模式,所以跳過接下來的4章,直接進入到命令模式的學習~

命令模式

英文:Command
這個名字是不是很熟悉?

what

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

場景

宿舍有人過生日,所以預定了一個飯店。我們需要點餐,服務員(介面)進行記錄,當點到熊掌鮑魚時,服務員答道:今天沒有這道菜,請點其他菜品~(else語句,沒貨進行回絕),然後我們點好了,服務員告訴了廚師,並對賬目進行了彙總(記錄賬單),這時候有個朋友要去一份沙拉(取消訂單),加一份大盤雞,我們又叫來了服務員,服務員將賬單改好(設定訂單)後又通知了廚師去做(執行

優點

  1. 容易設計一個命令佇列
  2. 容易將命令記入日誌
  3. 允許接收請求的一方決定是否否決請求
  4. 容易實現對請求的撤銷喝重做
  5. 由於加進新的具體命令類不影響其他的類,因此增加新的具體命令類很容易
  6. 把請求一個操作的物件與知道怎麼執行一個操作的物件分割開

注意

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

錯誤解決

可訪問性不一致
錯誤

解決:

原因:返回引數的訪問級別小於函式的訪問級別,也就是說當定義一個返回引數的方法的時候,如果返回引數的訪問級別低於方法的訪問級別就會出現這樣的錯誤,比如private,public,protect等。
錯誤程式碼:

class Barbecuer

正確程式碼:

public class Barbecuer

程式碼展示

烤肉串者(廚師):

public class Barbecuer
    {
        //烤羊肉串
        public void BakeMutton()
        {
            Console.WriteLine("烤羊肉串,好吃不貴!");
        }

        //烤雞
        public void BakeChicken()
        {
            Console.WriteLine("烤雞,好吃不貴!");
        }
    }

抽象命令類:

public abstract class Command
    {
        protected Barbecuer receiver;

        //抽象命令類,只需確定“烤肉串者”是誰即可
        public Command(Barbecuer receiver)
        {
            this.receiver = receiver;
        }

        //執行命令
        abstract public void ExcuteCommand();
    }

服務員類:(命令者介面)

//服務員類,不用管使用者想要什麼,反正是命令,只管記錄訂單,然後通知烤肉者執行即可。
public class Waiter
    {
        private Command command;

        //設定訂單
        public void SetOrder(Command command)
        {
            this.command = command;
        }

        //通知執行
        public void Notify()
        {
            command.ExcuteCommand();
        }
    }

具體命令類:

//具體命令類:

    //烤羊肉串類
    class BakeMuttonCommand:Command 
    {
        public BakeMuttonCommand(Barbecuer receiver)
            : base(receiver)
        {
        }

        //重寫方法,具體命令類,執行命令時,執行具體行為

        public override void ExcuteCommand()
        {
            receiver.BakeMutton();
        }
    }

    //烤雞類
    class BakeChickenCommand : Command
    {
        public BakeChickenCommand(Barbecuer receiver)
            : base(receiver)
        {
        }

        public override void ExcuteCommand()
        {
            receiver.BakeChicken();
        }
    } 

客戶端程式碼:

class Program
    {
        static void Main(string[] args)
        {
            //開店前準備
            Barbecuer monkey = new Barbecuer();
            Command bakeMuttonCommand1 = new BakeMuttonCommand(monkey);
            Command bakeMuttonCommand2 = new BakeMuttonCommand(monkey);
            Command bakeChickenCommand1 = new BakeChickenCommand(monkey);
            Waiter mm = new Waiter();

            //開門營業,服務員根據使用者要求,通知廚房開始製作
            mm.SetOrder(bakeMuttonCommand1);
            mm.Notify();  //呼叫通知
            mm.SetOrder(bakeMuttonCommand2);
            mm.Notify();
            mm.SetOrder(bakeChickenCommand1);
            mm.Notify();

            Console.Read();
        }
    }

效果展示:

展示

後記

本來是很簡單的一個模式,但是由於大小寫等一些問題,找了半天的解決方案,不過最終的成就感顯得更高一些~

相關文章