1、定義dom
職責鏈模式:使得多個對象都有機會處理請求,從而避免請求的發送者和接受者之間的耦合關係。將這個對象連成一條鏈,並沿着這條鏈傳遞該請求,直到有一個對象處理它爲止。ide
解釋:簡單來講應該是對於一個請求,不一樣的人根據本身職責範圍對它進行處理,同時也由於它通常是從底層向上層傳遞的請求的,因此將處理該請求的不一樣的對象比喻成一個鏈,從相對「低」的地方傳遞到相對「高」的地方,從而完成請求操做。性能
2、UML類圖及基本代碼this
基本代碼:spa
abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console.WriteLine("{0}處理請求{1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } 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); } } } 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); } } }
客戶端調用及其結果:3d
Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); int[] requests = { 6, 5, 14, 23, 18, 9, 17, 6, 26 }; foreach (int request in requests) { h1.HandleRequest(request); }
3、具體實例code
列舉一個能更加說明職責鏈的實例。john在單位,向領導請假,小於等於2天經理有權利批准,小於等於5天總監有權利批准,其餘的則要交到總經理那裏批准。具體代碼以下:對象
class Request { public string RequestType{get;set;} public string RequestContent{get;set;} public int Number{get;set;} } abstract class Manager { protected string name; protected Manager superior; public Manager(string name) { this.name = name; } public void SetSuperior(Manager superior) { this.superior = superior; } public abstract void RequestApplications(Request request); } class CommonManager : Manager { public CommonManager(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "leave" && request.Number <= 2) { Console.WriteLine("{0}:{1} number is {2} ok", name, request.RequestContent, request.Number); } else { if (superior != null) { superior.RequestApplications(request); } } } } class Majordome : Manager { public Majordome(string name) : base(name) { } public override void RequestApplications(Request request) { if (request.RequestType == "leave" && request.Number <= 5) { Console.WriteLine("{0}:{1} number is {2} ok", 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 == "leave") { Console.WriteLine("{0}:{1} number is {2} ok", name, request.RequestContent, request.Number); } else if (request.RequestType == "add money" && request.Number <= 500) { Console.WriteLine("{0}:{1} number is {2} ok", name, request.RequestContent, request.Number); } else if (request.RequestType == "add money" && request.Number > 500) { Console.WriteLine("{0}:{1} number is {2} not ok", name, request.RequestContent, request.Number); } } }
客戶端調用及結果:blog
CommonManager jinli = new CommonManager("經理"); Majordome zongjian = new Majordome("總監"); GeneralManager zhongjingli = new GeneralManager("總經理"); jinli.SetSuperior(zongjian); zongjian.SetSuperior(zhongjingli); Request request = new Request(); request.RequestType = "leave"; request.RequestContent = "john ask for days"; request.Number = 2; jinli.RequestApplications(request); Request request2 = new Request(); request2.RequestType = "leave"; request2.RequestContent = "john ask for days"; request2.Number = 5; jinli.RequestApplications(request2);
4、優缺點及適用場景get
優勢:
1)下降了請求發送者和處理者之間的耦合。
2)把多個條件斷定分散到各個處理類中,使得代碼更加清晰,責任更加明確。
缺點:
1)在找到正確的處理對象以前,全部的條件斷定都要執行一遍,當職責鏈過長時,可能會引發性能問題。
2)可能致使某個請求不被處理。
適用場景:
1)一個系統的請求須要多個對象進行審批才能完成的狀況。
2)代碼中有多個if-else時,也能夠考慮使用職責鏈模式對代碼進行重構。