命令模式(Command),將一個請求封裝爲一個對象,從而使你可用不一樣的請求對客戶進行參數化;對請求排隊或記錄請求日誌,以及支持可撤銷操做。javascript
下面給出命令模式的結構圖:html
下面是命令模式的基本結構代碼:java
namespace ConsoleApplication1 { abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } abstract public void Execute(); } //ConcreteCommand類,將一個接收者對象綁定於一個動做,調用接收者相應的操做,以實現Execute class ConcreteCommand : Command { public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Execute() { receiver.Action(); } } //Invoker類,要求該命令執行這個請求 class Invoker { private Command command; public void SetCommand(Command command) { this.command = command; } public void ExecuteCommand() { command.Execute(); } } //Receiver類,知道如何實施與執行一個請求相關的操做,任何類均可能做爲一個接收者 class Receiver { public void Action() { Console.WriteLine("執行請求!"); } } class Program { static void Main(string[] args) { Receiver r = new Receiver(); Command c = new ConcreteCommand(r); Invoker i = new Invoker(); i.SetCommand(c); i.ExecuteCommand(); Console.ReadKey(); } } }
命令模式的優勢:git
一、它能較容易地設計一個命令隊列;設計模式
二、在須要的狀況下,能夠叫容易地將命令計入日誌;ide
三、容許接收請求的一方決定是否要否決請求。post
四、能夠容易地實現對請求的撤銷和重作;學習
五、因爲加進新的具體命令類不影響其餘的類,所以增長新的具體命令類很容易。this
六、最關鍵的一點,命令模式把請求一個操做的對象與知道怎麼執行一個操做的對象分割開。spa
回到《大話設計模式》書中的燒烤例子:
namespace ConsoleApplication1 { public class Barbecuer { //烤羊肉 public void BakeMutton() { Console.WriteLine("烤羊肉串"); } //烤雞翅 public void BakeChickenWing() { Console.WriteLine("烤雞翅"); } } //抽象命令 public abstract class Command { protected Barbecuer receiver; public Command(Barbecuer receiver) //抽象命令類,只須要肯定‘烤羊肉串者’是誰 { this.receiver = receiver; } //執行命令 abstract public void ExecuteCommand(); } //烤羊肉串命令 class BakeMuttonCommand : Command { public BakeMuttonCommand(Barbecuer receiver) : base(receiver) { } public override void ExecuteCommand() { receiver.BakeMutton(); } } //烤雞翅命令 class BakeChickenWingCommand : Command { public BakeChickenWingCommand(Barbecuer receiver) : base(receiver) { } public override void ExecuteCommand() { receiver.BakeChickenWing(); } } //服務員類 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.ExecuteCommand(); } } } class Program { 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.ReadKey(); } } }