設計模式(10)---命令模式

1、引言:ide

  路邊有一個烤肉攤,有一位老闆負責給客人燒烤食物。若是客人不多,老闆都能準確記住你們的要求,隨着客人的增多,要求愈來愈多,老闆很難知足你們要求,老闆應該怎麼辦?this

首先說明爲何客人多了,老闆知足不了你們的要求,由於「用程序猿的話說是由於:緊耦合」。鬆耦合就能很好的解決此問題,也就是本文介紹的命令模式。先給出緊耦合代碼:spa

class Program
    {
        static void Main(string[] args)
        {
            Receiver receiver = new Receiver();
            receiver.BakeChickenWing();

            Console.Read();
        }
    }

    public class Receiver//boss
    {
        public void BakeMutton()
        {
            Console.WriteLine("bake mutton");
        }

        public void BakeChickenWing()
        {
            Console.WriteLine("bake chickenwing");
        }
    }
View Code

 

2、定義:設計

命令模式:將一個請求封裝爲一個對象,從而使你可用不一樣的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷操做。3d

解釋:將請求命令封裝爲一個對象,並用日誌記錄下來,其中它支持命令撤銷功能。日誌

 

3、UML圖及基本代碼:code

基本代碼:對象

class Receicer
    {
        public void Action()
        {
            Console.WriteLine("執行請求");
        }
    }

    abstract class Command
    {
        protected Receicer receiver;

        public Command(Receicer receiver)
        {
            this.receiver = receiver;
        }

        abstract public void Execute();
    }

    class ConcreteCommand : Command
    {
        public ConcreteCommand(Receicer receiver)
            : base(receiver)
        { }

        public override void Execute()
        {
            receiver.Action();
        }
    }

    class Invoker
    {
        private Command command;

        public void SetCommand(Command command)
        {
            this.command = command;
        }

        public void ExecuteCommand()
        {
            command.Execute();
        }
    }

調用:blog

Receicer receiver = new Receicer();
            Command command = new ConcreteCommand(receiver);
            Invoker invoker = new Invoker();
invoker.SetCommand(command);

invoker.ExecuteCommand();

解釋:映射客人到酒店就餐。Receiver是命令的接收者,至關於酒店中的大廚;Command命令抽象類,ConcreteCommand是具體的命令,至關於點菜請求,命令中應該包含命令的接收者。Invoke是命令的傳達者,至關於酒店的服務員,負責記錄客人點菜請求,並傳達給後廚。隊列

 

4、舉例說明:

 學校高一學生進行軍訓,校長髮佈讓學生跑10000米的命令。整個過程:校長髮布命令給軍訓教官,教官傳達校長命令給學生,學生接收到命令後執行相應的操做。在下面實例中,Receiver是學生,操做跑10000米的命令。Command是命令,必需知道命令的接收者。Drillmaster是教官,教官必需知道命令是什麼,並傳達命令。

//校長髮布學生跑1000米的命令,教官傳達此命令給學生,學生是命令的接收者
    //客戶端:校長,命令的發出者必須知道具體的命令、接受者、傳達命令者
    class Program
    {
        static void Main(string[] args)
        {
            Receiver receiver = new Receiver();
            Command command = new ConcreteCommand(receiver);
            Drillmaster drillmaster = new Drillmaster(command);
            drillmaster.ExecuteCommand();

            Console.Read();
        }
    }

    //命令接收者
    public class Receiver
    {
        public void Run1000Meters()
        {
            Console.WriteLine("跑10000米");
        }
    }

    //抽象命令
    public abstract class Command
    {
        protected Receiver receiver;

        public Command(Receiver receiver)
        {
            this.receiver = receiver;
        }

        public abstract void Action();
    }

    //具體的命令,必須知道命令接受者
    public class ConcreteCommand : Command
    {
        public ConcreteCommand(Receiver receiver)
            : base(receiver)
        { }

        public override void Action()
        {
            receiver.Run1000Meters();
        }
    }

    //教官:命令的傳達者,負責調用命令對象的方法來保證命令執行
    public class Drillmaster
    {
        public Command command;

        public Drillmaster(Command command)
        {
            this.command = command;
        }

        public void ExecuteCommand()
        {
            command.Action();
        }
    }
View Code

 

5、解決引言中的問題

客人點菜命令的接收者,老闆(大廚):

public class Receiver
    {
        public void BakeMutton()
        {
            Console.WriteLine("bake mutton");
        }

        public void BakeChickenWing()
        {
            Console.WriteLine("bake chickenwing");
        }
    }

 

點菜命令:

public abstract class Command
    {
        protected Receiver receiver;

        public Command(Receiver receiver)
        {
            this.receiver = receiver;
        }

        abstract public void Execute();
    }

    class ConcreteCommand1 : Command
    {
        public ConcreteCommand1(Receiver receiver)
            : base(receiver)
        { }

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

    class ConcreteCommand2 : Command
    {
        public ConcreteCommand2(Receiver receiver)
            : base(receiver)
        { }

        public override void Execute()
        {
            receiver.BakeChickenWing();
        }
    }

 

增長一個服務生,負責記錄客人點菜命令,並傳達給大廚。點菜命令能夠進行增長或取消操做。

public class Invoker
    {
        private IList<Command> commands = new List<Command>();

        public void AddCommand(Command command)
        {
            commands.Add(command);
            Console.WriteLine("增長訂單" + command.ToString());
        }

        public void CancelCommand(Command command)
        {
            commands.Remove(command);
            Console.WriteLine("取消訂單" + command.ToString());
        }

        public void ExecuteCommand()
        {
            foreach (Command command in commands)
            {
                command.Execute();
            }
        }
    }

 

客戶端調用:

Receiver receiver = new Receiver();
            Command command1 = new ConcreteCommand1(receiver);
            Command command2 = new ConcreteCommand2(receiver);
            Invoker invoker = new Invoker();

            invoker.AddCommand(command1);
            invoker.AddCommand(command2);
            invoker.CancelCommand(command1);
            invoker.ExecuteCommand();

 

6、優缺點及適用場景

優勢:

比較容易的設計一個命令隊列;在須要的狀況下,能夠比較容易的將命令計入日誌;容許接收請求的一方決定是否要否決請求;比較容易的對命令實現撤銷和重作;因爲加入新的具體命令類不影響其餘的類,所以增長新的具體命令類比較容易。

缺點:

可能會致使系統具備過多的具體命令類。

 

適用場景:

我的理解:基本上能表現其優勢的地方均可以使用命令模式。

 

補充:

命令模式其實就是一對象發佈命令,另一個對象來執行。若是發出多個命令,其中一些命令發出後能夠撤銷,一些命令能夠重複發出,等等複雜的操做。須要增長一個對象,對這些命令進行管理記錄,並隨時增長或者刪除。同時若是新增長命令,沒必要對其餘的對象形成過多的影響。

相關文章
相關標籤/搜索