職責鏈模式(Chain of Responsibility):使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。將這個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它位置。javascript
下面給出職責鏈模式的結構圖:html
下面給出職責鏈模式的基本代碼結構:java
namespace ConsoleApplication1 { //Handler類,定義一個處理請示的接口 abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } //ConcreteHandler1類,具體處理者類,處理它所負責的請求,可訪問它的後繼者,若是可處理該請求,就處理,不然將請求轉發給它的後繼者。 class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) //0到10處理此請求 { Console.WriteLine("{0}處理請求{1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); //轉移到下一位 } } } //ConcreteHandler2類,具體處理者,當請求數在10到20之間則有權處理,不然轉到下一位 class ConcreteHandler2 : Handler { public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Console.WriteLine("{0}處理請求{1}",this.GetType().Name,request); } else if (successor != null) { successor.HandleRequest(request); } } } //ConcreteHandler3類,具體處理者,當請求數在20到30之間則有權處理,不然轉到下一位 class ConcreteHandler3 : Handler { public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.WriteLine("{0}處理請求{1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } class Program { static void Main(string[] args) { Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); //設置h1的後繼者,當它處理不了的時候,會將請求傳給後繼者 h2.SetSuccessor(h3); //設置h2的後繼者,當它處理不了的時候,會將請求傳給後繼者 int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; foreach (int request in requests) { h1.HandleRequest(request); //這樣還有一個好處,只要將請求給h1,它就會自動找人搞定,不會像某某部門同樣踢皮球 } Console.ReadKey(); } } }
結果以下所示:git
當客戶端提交一個請求,請求是沿鏈傳遞直至有一個ConcreteHandler對象負責處理它。這就使得接收者和發送者都沒有對方的明確信息,且鏈中的對象本身也不知道鏈的結構。結果是職責鏈可簡化對象的相互鏈接,他們僅需保持一個指向其後繼的引用而不需保持它全部的候選接收者的引用。同時你也能夠隨時增長或修改處理一個請求的結構,加強了給對象指派職責的靈活性。設計模式
可是要小心,由於一個請求極有可能到了鏈的末端都得不處處理,或者由於沒有正確配置而得不處處理。因此須要事先考慮全面。dom
下面回到《大話設計模式》中的加薪代碼:ide
namespace ConsoleApplication1 { //申請 class Request { //申請類別 private string requestType; public string RequestType { get { return requestType; } set { requestType = value; } } //申請內容 private string requestContent; public string RequestContent { get { return requestContent; } set { requestContent = value; } } //數量 private int number; public int Number { get { return number; } set { number = value; } } } //管理者 abstract class Manager { protected string name; //管理者的上級 protected Manager superior; public Manager(string name) { this.name = name; } //設置管理者上級 public void SetSuperior(Manager superior) { this.superior = superior; } //申請請求 abstract public void RequestApplications(Request request); } //經理 class CommonManager : Manager { public CommonManager(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "請假" && request.Number <= 2) { Console.WriteLine("{0}:{1}數量{2}被批准", name, request.RequestContent, request.Number); } else { if (superior != null) { superior.RequestApplications(request); } } } } //總監 class Majordomo : Manager { public Majordomo(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "請假" && request.Number <= 5) { Console.WriteLine("{0}:{1}數量{2}被批准", name, request.RequestContent, request.Number); } else { if (superior != null) { superior.RequestApplications(request); } } } } //總經理 class GeneralManager : Manager { public GeneralManager(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "請假") { Console.WriteLine("{0}:{1}數量{2}被批准", name, request.RequestContent, request.Number); } else if (request.RequestType == "加薪" && request.Number <= 500) { Console.WriteLine("{0}:{1}數量{2}被批准",name,request.RequestContent,request.Number); } else if (request.RequestType == "加薪" && request.Number > 500) { Console.WriteLine("{0}:{1}數量{2},再說吧", name, request.RequestContent, request.Number); } } } class Program { static void Main(string[] args) { CommonManager jinli = new CommonManager("金利"); Majordomo zongjian = new Majordomo("宗劍"); GeneralManager zongjinli = new GeneralManager("鍾金麗"); jinli.SetSuperior(zongjian); //設置經理上級 zongjian.SetSuperior(zongjinli); //設置總監上級 Request request = new Request(); request.RequestType = "請假"; request.RequestContent = "小菜請假"; request.Number = 1; jinli.RequestApplications(request); Request request2 = new Request(); request2.RequestType = "請假"; request2.RequestContent = "小菜請假"; request2.Number = 4; jinli.RequestApplications(request2); Request request3 = new Request(); request3.RequestType = "加薪"; request3.RequestContent = "小菜請求加薪"; request3.Number = 500; jinli.RequestApplications(request3); Request request4 = new Request(); request4.RequestType = "加薪"; request4.RequestContent = "小菜請求加薪"; request4.Number = 1000; jinli.RequestApplications(request4); Console.ReadKey(); } } }
結果如圖所示:post