Head First設計模式——生成器和責任鏈模式
- 2020 年 3 月 13 日
- 筆記
生成器
生成器模式:封裝一個產品的構造過程,並允許按步驟構造。
現又一個度假計劃指定,需要指定度假每一天的活動、旅館、用餐、門票等等事情,但是每個客人的度假計劃可能不太一樣。例如天數、活動類型、用餐等等。
我們需要一個彈性的數據結構,代表客人的規劃,以及不同的變化,也需要一系列潛在複雜順序,創建這樣的規劃。如何提供一種方式來創建複雜的結構,也不會和創建它的步驟混在一起。迭代器的過程就是封裝進一個獨立的對象中,向客戶隱藏集合的內部表現。這裡我們也採用同樣的思路:我們將旅遊規劃的創建過程,封裝到一個對象中(此對象稱為生成器),然後讓客戶調用生成器為它創建旅遊規劃。
設計類圖:
實現程式碼:
①存儲數據結構類
1 public class Vacation 2 { 3 public int Day { get; set; } 4 public string Hotel { get; set; } 5 public string Park { get; set; } 6 public string Activity { get; set; } 7 public string Meal { get; set; } 8 }
②抽象生成器
1 public abstract class AbstractBuilder 2 { 3 public abstract void BuildDay(int day); 4 public abstract void Hotel(string hotel); 5 public abstract void Park(string park); 6 public abstract void Activity(string activity); 7 public abstract void Meal(string meal); 8 public abstract Vacation GetVacationPlanner(); 9 }
③具體生成器,具體生成器可以多個實現。
1 public class VacationBuilder : AbstractBuilder 2 { 3 private Vacation vacation=new Vacation(); 4 5 public override void BuildDay(int day) 6 { 7 vacation.Day = day; 8 } 9 10 public override void Hotel(string hotel) 11 { 12 vacation.Hotel = hotel; 13 } 14 public override void Activity(string activity) 15 { 16 vacation.Activity = activity; 17 } 18 public override void Meal(string meal) 19 { 20 vacation.Meal = meal; 21 } 22 23 public override void Park(string park) 24 { 25 vacation.Park = park; 26 } 27 28 public override Vacation GetVacationPlanner() 29 { 30 return vacation; 31 } 32 }
④客戶使用生成器
優點:
1、將複雜對象創建過程封裝起來。
2、允許對象通過多個步驟來創建,並且可以改變過程。
3、向客戶隱藏產品內部表現。
4、產品的實現可以被替換,因為客戶只看到一個抽象的介面。
用途與缺點:
1、經常用來創建組合結構。
2、與工廠模式相比,採用生成器創建對象的客戶需要更多的領域知識,才能正確的創建對象。
責任鏈
責任鏈模式:讓一個以上的對象有機會能夠處理某個請求的時候,就使用責任鏈模式。
有這樣一個場景,公司專門接受郵件處理的人員需要將每天接收到的郵件進行處理,一類是需要轉給部門經理處理的郵件,一類是給自己處理的,還有一類垃圾郵件直接刪除。如果這樣的一個場景,我們就可以通過責任鏈模式,為處理創建一個對象鏈。每個對象依序檢查郵件請求,並進行處理,或者將它傳遞給鏈中的下一個對象。
設計類圖:
實現程式碼:
①責任鏈抽象類
1 /// <summary> 2 /// 郵件類型 3 /// </summary> 4 public enum EmailType 5 { 6 Self=1, 7 Manager=2, 8 Del=3 9 } 10 11 12 public abstract class Handler 13 { 14 public Handler nextHandler; 15 public EmailType type; 16 17 public Handler(EmailType type) { 18 this.type = type; 19 } 20 21 public void SetNextHandler(Handler nextHandler) 22 { 23 this.nextHandler = nextHandler; 24 } 25 26 public abstract void HandleRequest(EmailType requsetType); 27 28 }
②責任鏈處理類
1 /// <summary> 2 /// 自己處理 3 /// </summary> 4 class SelfHandler : Handler 5 { 6 public SelfHandler() : base(EmailType.Self) 7 { 8 } 9 10 public override void HandleRequest(EmailType requsetType) 11 { 12 if (EmailType.Self == requsetType) 13 { 14 Console.WriteLine("郵件由自己處理"); 15 } 16 else 17 { 18 if (nextHandler != null) 19 { 20 nextHandler.HandleRequest(requsetType); 21 } 22 } 23 } 24 }
1 /// <summary> 2 /// 轉發經理 3 /// </summary> 4 class ManagerHandler : Handler 5 { 6 public ManagerHandler() : base(EmailType.Manager) 7 { 8 } 9 10 public override void HandleRequest(EmailType requsetType) 11 { 12 if (EmailType.Manager == requsetType) 13 { 14 Console.WriteLine("郵件轉到經理處理"); 15 } 16 else 17 { 18 if (nextHandler != null) 19 { 20 nextHandler.HandleRequest(requsetType); 21 } 22 } 23 } 24 }
1 /// <summary> 2 /// 刪除垃圾郵件 3 /// </summary> 4 class DelHandler : Handler 5 { 6 public DelHandler() : base(EmailType.Del) 7 { 8 } 9 10 public override void HandleRequest(EmailType requsetType) 11 { 12 if (EmailType.Del == requsetType) 13 { 14 Console.WriteLine("垃圾郵件已刪除"); 15 } 16 else 17 { 18 if (nextHandler != null) 19 { 20 nextHandler.HandleRequest(requsetType); 21 } 22 } 23 } 24 }
③測試責任鏈
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //組裝責任鏈 6 Handler handler = new SelfHandler(); 7 Handler handler1 = new ManagerHandler(); 8 Handler handler2 = new DelHandler(); 9 handler.SetNextHandler(handler1); 10 handler1.SetNextHandler(handler2); 11 //測試 12 handler.HandleRequest(EmailType.Del); 13 handler.HandleRequest(EmailType.Manager); 14 handler.HandleRequest(EmailType.Self); 15 16 Console.ReadKey(); 17 } 18 }
優點:
1、請求的發送者和接收者解耦。
2、簡化對象,因為不需要知道鏈的結構。
3、通過改變鏈內的成員或調動他們的次序,允許你動態地新增或者刪除責任。
用途和缺點:
1、經常被用在窗口系統中,處理滑鼠和鍵盤之類的事件。
2、並不保證請求一定被執行,如果沒有任何對象處理它,可能會落到鏈尾端之外。
3、不容易觀察允許特徵,不好排查問題。