設計模式14:Chain of Responsibility Pattern (職責鏈模式)

來源:互聯網
上載者:User

Define:Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

一、 職責鏈(Chain of Responsibility)模式

責任鏈模式是一種對象的行為模式【GOF95】。在責任鏈模式裡,很多個物件由每一個對象對其下家的引用而串連起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的用戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響用戶端的情況下動態地重新組織鏈和分配責任。

從擊鼓傳花談起

擊鼓傳花是一種熱鬧而又緊張的飲酒遊戲。在酒宴上賓客依次坐定位置,由一人擊鼓,擊鼓的地方與傳花的地方是分開的,以示公正。開始擊鼓時,花束就開始依次傳遞,鼓聲一落,如果花束在某人手中,則該人就得飲酒。

擊鼓傳花便是責任鏈模式的應用。責任鏈可能是一條直線、一個環鏈或者一個樹結構的一部分。

二、 責任鏈模式的結構

 

責任鏈模式涉及到的角色如下所示:

抽象處理者(Handler)角色:定義出一個處理請求的介面。如果需要,介面可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類別或介面實現。

具體處理者(ConcreteHandler)角色:具體處理者接到請求後,可以選擇將請求處理掉,或者將請求傳給下家。由於具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。

三、 責任鏈模式的示意性原始碼

using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Text;</p><p>namespace Chain_of_Respon_Pattern<br />{<br /> abstract class Handler<br /> {<br /> // Fields<br /> protected Handler successor;</p><p> // Methods<br /> public void SetSuccessor(Handler successor)<br /> {<br /> this.successor = successor;<br /> }<br /> abstract public void HandleRequest(int request);<br /> }</p><p> // "ConcreteHandler1"<br /> class ConcreteHandler1 : Handler<br /> {<br /> // Methods<br /> override public void HandleRequest(int request)<br /> {<br /> if (request >= 0 && request < 10)<br /> Console.WriteLine("{0} handled request {1}",<br /> this, request);<br /> else<br /> if (successor != null)<br /> successor.HandleRequest(request);<br /> }<br /> }</p><p> // "ConcreteHandler2"<br /> class ConcreteHandler2 : Handler<br /> {<br /> // Methods<br /> override public void HandleRequest(int request)<br /> {<br /> if (request >= 10 && request < 20)<br /> Console.WriteLine("{0} handled request {1}",<br /> this, request);<br /> else<br /> if (successor != null)<br /> successor.HandleRequest(request);<br /> }<br /> }</p><p> // "ConcreteHandler3"<br /> class ConcreteHandler3 : Handler<br /> {<br /> // Methods<br /> override public void HandleRequest(int request)<br /> {<br /> if (request >= 20 && request < 30)<br /> Console.WriteLine("{0} handled request {1}",<br /> this, request);<br /> else<br /> if (successor != null)<br /> successor.HandleRequest(request);<br /> }<br /> }</p><p> /**/<br /> /// <summary><br /> /// Client test<br /> /// </summary><br /> public class Client<br /> {<br /> public static void Main(string[] args)<br /> {<br /> // Setup Chain of Responsibility<br /> Handler h1 = new ConcreteHandler1();<br /> Handler h2 = new ConcreteHandler2();<br /> Handler h3 = new ConcreteHandler3();<br /> h1.SetSuccessor(h2);<br /> h2.SetSuccessor(h3);</p><p> // Generate and process request<br /> int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };</p><p> foreach (int request in requests)<br /> h1.HandleRequest(request);<br /> Console.Read();</p><p> }<br /> }<br />}<br />  

四、 純的與不純的責任鏈模式

一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行為中選擇一個:一個是承擔責任,二是把責任推給下家。不允許出現某一個具體處理者對象在承擔了一部分責任後又把責任向下傳的情況。

在一個純的責任鏈模式裡面,一個請求必須被某一個處理者對象所接收;在一個不純的責任鏈模式裡面,一個請求可以最終不被任何接收端對象所接收。純的責任鏈模式的例子是不容易找到的,一般看到的例子均是不純的責任鏈模式的實現。

五、 責任鏈模式的實際應用案例

下面的責任鏈模式代碼示範了不同職務的人根據所設定的許可權對一個購買請求作出決策或將其交給更高的決策者。

using System;<br />using System.Collections.Generic;<br />using System.Linq;<br />using System.Text;</p><p>namespace Chain_of_Respon_Pattern<br />{<br /> abstract class Approver<br /> {<br /> // Fields<br /> protected string name;<br /> protected Approver successor;</p><p> // Constructors<br /> public Approver(string name)<br /> {<br /> this.name = name;<br /> }</p><p> // Methods<br /> public void SetSuccessor(Approver successor)<br /> {<br /> this.successor = successor;<br /> }</p><p> abstract public void ProcessRequest(PurchaseRequest request);<br /> }</p><p> // "ConcreteHandler"<br /> class Director : Approver<br /> {<br /> // Constructors<br /> public Director(string name) : base(name) { }</p><p> // Methods<br /> override public void ProcessRequest(PurchaseRequest request)<br /> {<br /> if (request.Amount < 10000.0)<br /> Console.WriteLine("{0} {1} approved request# {2}",<br /> this, name, request.Number);<br /> else<br /> if (successor != null)<br /> successor.ProcessRequest(request);<br /> }<br /> }</p><p> // "ConcreteHandler"<br /> class VicePresident : Approver<br /> {<br /> // Constructors<br /> public VicePresident(string name) : base(name) { }</p><p> // Methods<br /> override public void ProcessRequest(PurchaseRequest request)<br /> {<br /> if (request.Amount < 25000.0)<br /> Console.WriteLine("{0} {1} approved request# {2}",<br /> this, name, request.Number);<br /> else<br /> if (successor != null)<br /> successor.ProcessRequest(request);<br /> }<br /> }</p><p> // "ConcreteHandler"<br /> class President : Approver<br /> {<br /> // Constructors<br /> public President(string name) : base(name) { }<br /> // Methods<br /> override public void ProcessRequest(PurchaseRequest request)<br /> {<br /> if (request.Amount < 100000.0)<br /> Console.WriteLine("{0} {1} approved request# {2}",<br /> this, name, request.Number);<br /> else<br /> Console.WriteLine("Request# {0} requires " +<br /> "an executive meeting!", request.Number);<br /> }<br /> }</p><p> // Request details<br /> class PurchaseRequest<br /> {<br /> // Member Fields<br /> private int number;<br /> private double amount;<br /> private string purpose;</p><p> // Constructors<br /> public PurchaseRequest(int number,<br /> double amount, string purpose)<br /> {<br /> this.number = number;<br /> this.amount = amount;<br /> this.purpose = purpose;<br /> }</p><p> // Properties<br /> public double Amount<br /> {<br /> get { return amount; }<br /> set { amount = value; }<br /> }</p><p> public string Purpose<br /> {<br /> get { return purpose; }<br /> set { purpose = value; }<br /> }</p><p> public int Number<br /> {<br /> get { return number; }<br /> set { number = value; }<br /> }<br /> }</p><p> /**/<br /> /// <summary><br /> /// ChainApp Application<br /> /// </summary><br /> public class ChainApp<br /> {<br /> public static void Main(string[] args)<br /> {<br /> // Setup Chain of Responsibility<br /> Director Larry = new Director("Larry");<br /> VicePresident Sam = new VicePresident("Sam");<br /> President Tammy = new President("Tammy");<br /> Larry.SetSuccessor(Sam);<br /> Sam.SetSuccessor(Tammy);</p><p> // Generate and process different requests<br /> PurchaseRequest rs = new PurchaseRequest(2034, 350.00, "Supplies");<br /> Larry.ProcessRequest(rs);</p><p> PurchaseRequest rx = new PurchaseRequest(2035, 32590.10, "Project X");<br /> Larry.ProcessRequest(rx);</p><p> PurchaseRequest ry = new PurchaseRequest(2036, 122100.00, "Project Y");<br /> Larry.ProcessRequest(ry);<br /> Console.Read();<br /> }<br /> }<br />}<br />  

六、 責任鏈模式的實現

責任鏈模式並不建立責任鏈。責任鏈的建立必須由系統的其它部分建立出來。

責任鏈模式降低了請求的發送端和接收端之間的耦合,使多個對象都有機會處理這個請求。一個鏈可以是一條線,一個樹,也可以是一個環。如所示,責任鏈是一個樹結構的一部分。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.