1. 模式意圖
使多個對象都有機會處理請求,進而避免請求的發送者和接受者之間的耦合關系。
在職責鍊模式裡,很多對象由每一個對象對其下家的引用而連接配接起來形成一條鍊。請求在這個鍊上傳遞,知道鍊上的某一個對象決定處理此請求。發出這個請求的用戶端并不知道鍊上的哪一個對象最終處理這個請求,這使得系統可以在不影響用戶端的情況下動态地重新組織鍊和配置設定職責。
純的與不純的職責鍊模式:
一個純的職責鍊模式要求一個具體的處理這對象隻能在兩個行為中選擇一個:一個是承擔職責;二是把職責推給下家。不允許出現某一個具體處理這對象在承擔了一部分職責後又把職責向下傳的情況。
在一個純的職責鍊模式裡面,一個請求必須被某一個處理者對象所接受;在一個不純的職責鍊模式裡,一個請求可以最終不被任何接收端對象所接受。
示例:

2. 模式定義
抽象處理者(Handler): 定義一個處理請求的接口;如果需要,可以定義一個方法,用以設定和傳回對下家的引用。
具體處理者(ConcreteHandler): 具體處理者接到請求後,可以選擇将請求處理掉,或者将請求傳給下家;
Client: 向鍊上的具體處理者對象送出請求。
職責鍊模式并不建立職責鍊,職責鍊的建立必須由系統的其他部分建立出來。
職責鍊可以是一條線,一個樹,也可以是一個環;如下,職責鍊是一個樹結構的一部分:
3. 模式實作
3.1 C#的職責鍊模式
// Chain of Responsibility pattern -- Structural example
using System;
// "Handler"
abstract class Handler
{
// Fields
protected Handler successor;
// Methods
public void SetSuccessor( Handler successor )
{
this.successor = successor;
}
abstract public void HandleRequest( int request );
}
// "ConcreteHandler1"
class ConcreteHandler1 : Handler
{
// Methods
override public void HandleRequest( int request )
{
if( request >= 0 && request < 10 )
Console.WriteLine("{0} handled request {1}",
this, request );
else
if( successor != null )
successor.HandleRequest( request );
}
}
// "ConcreteHandler2"
class ConcreteHandler2 : Handler
{
// Methods
override public void HandleRequest( int request )
{
if( request >= 10 && request < 20 )
Console.WriteLine("{0} handled request {1}",
this, request );
else
if( successor != null )
successor.HandleRequest( request );
}
}
// "ConcreteHandler3"
class ConcreteHandler3 : Handler
{
// Methods
override public void HandleRequest( int request )
{
if( request >= 20 && request < 30 )
Console.WriteLine("{0} handled request {1}",
this, request );
else
if( successor != null )
successor.HandleRequest( request );
}
}
/// <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
// Generate and process request
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
foreach( int request in requests )
h1.HandleRequest( request );
}
}