[Head First設計模式]山西面館中的設計模式——裝飾者模式html
[Head First設計模式]山西面館中的設計模式——觀察者模式設計模式
[Head First設計模式]山西面館中的設計模式——建造者模式ide
[Head First設計模式]餃子館(冬至)中的設計模式——工廠模式post
[Head First設計模式]一我的的平安夜——單例模式學習
[Head First設計模式]搶票中的設計模式——代理模式測試
[Head First設計模式]面向對象的3特徵5原則this
[Head First設計模式]雲南米線館中的設計模式——模版方法模式spa
這裏採用書中餐廳訂餐的例子。餐廳訂餐的例子仍是比較簡單的,也比較好理解,書中的遙控器的例子,太長了,能把人繞暈,圖1:設計
圖2:
從餐廳到命令模式
Command:
定義命令的接口,聲明執行的方法。
ConcreteCommand:
具體的命令, 實現命令接口;一般會持有接收者,並調用接收者的功能來完成命令要執行的操做。
Receiver:
接收者,真正執行命令的對象。任何類均可能成爲一個接收者,只要它可以實現命令要求實現的相應功能。
Invoker:
要求命令對象執行請求,一般會持有命令對象,能夠持有不少的命令對象。這個是客戶端真正觸發命令並要求命令執行相應操做的地方,也就是說至關於使用命令對象的入口。
Client:
建立具體的命令對象,而且設置命令對象的接收者。注意這個不是咱們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱爲裝配者會更好理解,由於真正使用命令的客戶端是從Invoker來觸發執行。
這裏採用從實例到定義,倒着描述的方式,先從實例入手,有個大體印象,有助於理解。
將「請求」封裝成對象,以便使用不一樣的請求、隊列或者日誌來參數化其它對象。命令模式也支持可撤銷的操做。
分析:帥哥顧客,土豪訂單,美女服務員,資深大廚的角色是什麼?
帥哥顧客:Client
土豪訂單:實現Command接口的具體Command
美女服務員:Invoker
資深大廚:Receiver
代碼實現:
Command接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Wolfy.命令模式 { /// <summary> /// Command爲全部命令聲明一個接口,調用命令對象的excute方法 /// 就可讓接收者進行相關的動做, /// </summary> public abstract class Command { public abstract void Execute(); } }
OrderCommand:具體的命令,繼承自Command抽象類
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace Wolfy.命令模式 9 { 10 /// <summary> 11 /// 具體的命令 12 /// </summary> 13 public class OrderCommand : Command 14 { 15 /// <summary> 16 ///持有接受者對象 17 /// </summary> 18 SeniorChef receiver; 19 Order order; 20 public OrderCommand(SeniorChef receiver, Order order) 21 { 22 this.receiver = receiver; 23 this.order = order; 24 } 25 public override void Execute() 26 { 27 28 Console.WriteLine("{0}桌的訂單:", order.DiningTable); 29 foreach (string item in order.FoodDic.Keys) 30 { 31 //一般會轉調接收者對象的相應方法,讓接收者來真正執行功能 32 receiver.MakeFood(order.FoodDic[item],item); 33 } 34 Thread.Sleep(2000);//停頓一下 模擬作飯的過程 35 36 Console.WriteLine("{0}桌的飯弄好了", order.DiningTable); 37 } 38 } 39 }
Waitor:Invoker調用者,seniorChef:接收者 廚師類
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Wolfy.命令模式 { /// <summary> /// 美女服務員類 這裏做爲調用者Invoker的角色 /// </summary> public class Waitor { ArrayList commands = null;//能夠持有不少的命令對象 public Waitor() { commands = new ArrayList(); } public void SetCommand(Command cmd) { commands.Add(cmd); } /// <summary> /// 提交訂單 喊 訂單來了,廚師開始執行 /// </summary> public void OrderUp() { Console.WriteLine("美女服務員:叮咚,大廚,新訂單來了......."); Console.WriteLine("資深廚師:收到"); for (int i = 0; i < commands.Count; i++) { Command cmd = commands[i] as Command; if (cmd != null) { cmd.Execute(); } } } } }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Wolfy.命令模式 8 { 9 /// <summary> 10 /// 資深大廚類 是命令的Receiver 11 /// </summary> 12 public class SeniorChef 13 { 14 public void MakeFood(int num,string foodName) 15 { 16 Console.WriteLine("{0}份{1}", num,foodName); 17 } 18 } 19 }
訂單Order,封裝訂單內容,而後傳入OrderCommand,將訂單對象變爲命令對象
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Wolfy.命令模式 8 { 9 /// <summary> 10 /// 訂單 11 /// </summary> 12 public class Order 13 { 14 /// <summary> 15 /// 餐桌號碼 16 /// </summary> 17 public int DiningTable { set; get; } 18 /// <summary> 19 /// food key:飯名 value:多少份 20 /// </summary> 21 public Dictionary<string, int> FoodDic { set; get; } 22 } 23 }
測試端Program至關於Client角色
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace Wolfy.命令模式 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //program類 做爲客戶端 14 //建立2個order 15 Order order1 = new Order(); 16 order1.DiningTable = 1; 17 order1.FoodDic = new Dictionary<string, int>() ; 18 order1.FoodDic.Add("西紅柿雞蛋麪",1); 19 order1.FoodDic.Add("小杯可樂",2); 20 21 Order order2 = new Order(); 22 order2.DiningTable = 3; 23 order2.FoodDic = new Dictionary<string, int>(); 24 order2.FoodDic.Add("尖椒肉絲蓋飯", 1); 25 order2.FoodDic.Add("小杯雪碧", 1); 26 //建立接收者 27 SeniorChef receiver=new SeniorChef(); 28 //將訂單這個兩個消息封裝成命令對象 29 OrderCommand cmd1 = new OrderCommand(receiver, order1); 30 OrderCommand cmd2 = new OrderCommand(receiver, order2); 31 //建立調用者 waitor 32 Waitor invoker = new Waitor(); 33 //添加命令 34 invoker.SetCommand(cmd1); 35 invoker.SetCommand(cmd2); 36 //將訂單帶到櫃檯 並向廚師喊 訂單來了 37 invoker.OrderUp(); 38 Console.Read(); 39 } 40 } 41 }
測試結果:
命令模式優勢:
1.下降對象之間的耦合度。
2.新的命令能夠很容易地加入到系統中。
3.能夠比較容易地設計一個組合命令。
4.調用同一方法實現不一樣的功能
缺點:
使用命令模式可能會致使某些系統有過多的具體命令類。由於針對每個命令都須要設計一個具體命令類,所以某些系統可能須要大量具體命令類,這將影響命令模式的使用。
適用環境:
1.系統須要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。
2.系統須要在不一樣的時間指定請求、將請求排隊和執行請求。
3.系統須要支持命令的撤銷(Undo)操做和恢復(Redo)操做。
4.系統須要將一組操做組合在一塊兒,即支持宏命令。
今天在家研究了一天命令模式,以上爲我的理解,若有不妥之處,請指出,一塊兒交流學習,謝謝。
參考:
Head first 設計模式
百度百科