一、 職責鏈(Chain of Responsibility)模式
責任鏈模式是一種對象的行為模式【GOF95】。在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,
直到鏈上的某一個對象決定處理此請求。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新
組織鏈和分配責任。
從擊鼓傳花談起
擊鼓傳花是一種熱鬧而又緊張的飲酒游戲。在酒宴上賓客依次坐定位置,由一人擊鼓,擊鼓的地方與傳花的地方是分開的,以示公正。開始擊鼓時,花束就開始依次傳遞,鼓聲一落,如果花束在某人手中,則該人就得飲酒。
擊鼓傳花便是責任鏈模式的應用。責任鏈可能是一條直線、一個環(huán)鏈或者一個樹結構的一部分。
二、 責任鏈模式的結構
責任鏈模式涉及到的角色如下所示:

抽象處理者(Handler)角色:定義出一個處理請求的接口。如果需要,接口可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類或接口實現(xiàn)。
具體處理者(ConcreteHandler)角色:具體處理者接到請求后,可以選擇將請求處理掉,或者將請求傳給下家。由于具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
Chain of Responsibility模式的實現(xiàn)
要實現(xiàn)Chain of Responsibility模式,需要滿足該模式的基本要件:
1,對象鏈的組織。需要將某任務的所有職責執(zhí)行對象以鏈的形式加以組織。
2,消息或請求的傳遞。將消息或請求沿著對象鏈傳遞,以讓處于對象鏈中的對象得到處理機會。
3,處于對象鏈中的對象的職責分配。不同的對象完成不同的職責。
4,任務的完成。處于對象鏈的末尾的對象結束任務并停止消息或請求的繼續(xù)傳遞。
Chain of Responsibility模式的優(yōu)優(yōu)缺點:
優(yōu)點:
1,責任的分擔。每個類只需要處理自己該處理的工作(不該處理的傳遞給下一個對象完成),明確各類的責任范圍,符合類的最小封裝原則。
2,可以根據(jù)需要自由組合工作流程。如工作流程發(fā)生變化,可以通過重新分配對象鏈便可適應新的工作流程。
3,類與類之間可以以松耦合的形式加以組織。
缺點:
因為處理時以鏈的形式在對象間傳遞消息,根據(jù)實現(xiàn)方式不同,有可能會影響處理的速度。
例子:
namespace ChainOfResponsibility_DesignPattern
{
using System;
abstract class Handler
{
protected Handler successorHandler;
abstract public void HandleRequest(Request request);
public void SetSuccessor(Handler sucessor)
{
successorHandler = sucessor;
}
}
class ConcreteHandler1 : Handler
{
override public void HandleRequest(Request request)
{
// determine if we can handle the request
if (request.RequestType == 1) // some complex decision making!
{
// request handling code goes here
Console.WriteLine("request handled in ConcreteHandler1");
}
else
{
// not handled here - pass on to next in the chain
if (successorHandler != null)
successorHandler.HandleRequest(request);
}
}
}
class ConcreteHandler2 : Handler
{
override public void HandleRequest(Request request)
{
// determine if we can handle the request
if (request.RequestType == 2) // some complex decision making!
{
// request handling code goes here
Console.WriteLine("request handled in ConcreteHandler2");
}
else
{
// not handled here - pass on to next in the chain
if (successorHandler != null)
successorHandler.HandleRequest(request);
}
}
}
class ConcreteHandler3 : Handler
{
override public void HandleRequest(Request request)
{
// determine if we can handle the request
if (request.RequestType == 3) // some complex decision making!
{
// request handling code goes here
Console.WriteLine("request handled in ConcreteHandler3");
}
else
{
// not handled here - pass on to next in the chain
if (successorHandler != null)
successorHandler.HandleRequest(request);
}
}
}
class Request
{
private int iRequestType;
private string strRequestParameters;
public Request(int requestType, string requestParameters)
{
iRequestType = requestType;
strRequestParameters = requestParameters;
}
public int RequestType
{
get
{
return iRequestType;
}
set
{
iRequestType = value;
}
}
}
/// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
public static int Main(string[] args)
{
// Set up chain (usually one need to be done once)
Handler firstHandler = new ConcreteHandler1();
Handler secondHandler = new ConcreteHandler2();
Handler thirdHandler = new ConcreteHandler3();
firstHandler.SetSuccessor(secondHandler);
secondHandler.SetSuccessor(thirdHandler);
// After setting up the chain of responsibility, we can
// now generate requests and pass then off to the
// chain to be handled
// generate and fire request
Request newRequest = new Request(2,"This are the request parameters");
firstHandler.HandleRequest(newRequest);
return 0;
}
}
}