Head First設計模式之責任鏈模式
一、定義
避免請求發送者與接收者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,并且沿著這條鏈傳遞請求,直到有對象處理它為止。
主要解決:職責鏈上的處理者負責處理請求,客戶只需要將請求發送到職責鏈上即可,無須關心請求的處理細節和請求的傳遞,所以職責鏈將請求的發送者和請求的處理者解耦了。
何時使用:在處理消息的時候以過濾很多道。
如何解決:攔截的類都實現統一接口。
二、結構
從責任鏈模式的定義可以發現,責任鏈模式涉及的對象只有處理者角色,但由于有多個處理者,它們具有共同的處理請求的方法,所以這里抽象出一個抽象處理者角色進行代碼復用。這樣分析下來,責任鏈模式的結構圖也就不言而喻了,具體結構圖如下所示。

主要涉及兩個角色:
- 抽象處理者角色(Handler):定義出一個處理請求的接口。這個接口通常由接口或抽象類來實現。
- 具體處理者角色(ConcreteHandler):具體處理者接受到請求后,可以選擇將該請求處理掉,或者將請求傳給下一個處理者。因此,每個具體處理者需要保存下一個處理者的引用,以便把請求傳遞下去。
三、適用場景
1、有多個對象可以處理同一個請求,具體哪個對象處理該請求由運行時刻自動確定。
2、在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。
3、可動態指定一組對象處理請求。
四、優缺點
優點:
1、降低耦合度。它將請求的發送者和接收者解耦。
2、簡化了對象。使得對象不需要知道鏈的結構。
3、增強給對象指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。
4、增加新的請求處理類很方便。
缺點:
1、不能保證請求一定被接收。
2、系統性能將受到一定影響,而且在進行代碼調試時不太方便,可能會造成循環調用。
3、可能不容易觀察運行時的特征,有礙于除錯。
五、實現
以公司采購東西為例來實現責任鏈模式。公司規定,采購架構總價在1萬之內,經理級別的人批準即可,總價大于1萬小于2萬5的則還需要副總進行批準,總價大于2萬5小于10萬的需要還需要總經理批準,而大于總價大于10萬的則需要組織一個會議進行討論。
// 采購請求 public class PurchaseRequest { // 金額 public double Amount { get; set; } // 產品名字 public string ProductName { get; set; } public PurchaseRequest(double amount, string productName) { Amount = amount; ProductName = productName; } } // 審批人,Handler public abstract class Approver { public Approver NextApprover { get; set; } public string Name { get; set; } public Approver(string name) { this.Name = name; } public abstract void ProcessRequest(PurchaseRequest request); } // ConcreteHandler public class Manager : Approver { public Manager(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 10000.0) { Console.WriteLine("{0} 批準購買 {1}", Name, request.ProductName); } else if (NextApprover != null) { NextApprover.ProcessRequest(request); } } } // ConcreteHandler,副總 public class VicePresident : Approver { public VicePresident(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 25000.0) { Console.WriteLine("{0} 批準購買 {1}", Name, request.ProductName); } else if (NextApprover != null) { NextApprover.ProcessRequest(request); } } } // ConcreteHandler,總經理 public class President : Approver { public President(string name) : base(name) { } public override void ProcessRequest(PurchaseRequest request) { if (request.Amount < 100000.0) { Console.WriteLine("{0} 批準購買 {1}", Name, request.ProductName); } else { Console.WriteLine("Request需要組織一個會議討論"); } } } class Program { static void Main(string[] args) { PurchaseRequest requestTelphone = new PurchaseRequest(4000.0, "手機"); PurchaseRequest requestSoftware = new PurchaseRequest(10000.0, "空調"); PurchaseRequest requestComputers = new PurchaseRequest(40000.0, "筆記本電腦"); Approver manager = new Manager("經理"); Approver Vp = new VicePresident("副總"); Approver Pre = new President("總經理"); // 設置責任鏈 manager.NextApprover = Vp; Vp.NextApprover = Pre; // 處理請求 manager.ProcessRequest(requestTelphone); manager.ProcessRequest(requestSoftware); manager.ProcessRequest(requestComputers); Console.ReadLine(); } }
結果
經理 批準購買 手機
副總 批準購買 空調
總經理 批準購買 筆記本電腦
參考:
http://www.runoob.com/design-pattern/chain-of-responsibility-pattern.html
http://www.rzrgm.cn/zhili/p/ChainOfResponsibity.html
歡迎閱讀本系列文章:Head First設計模式之目錄

浙公網安備 33010602011771號