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

抽象處理者(Handler)角色:定義出一個(gè)處理請(qǐng)求的接口。如果需要,接口可以定義出一個(gè)方法,以設(shè)定和返回對(duì)下家的引用。這個(gè)角色通常由一個(gè)抽象類或接口實(shí)現(xiàn)。
具體處理者(ConcreteHandler)角色:具體處理者接到請(qǐng)求后,可以選擇將請(qǐng)求處理掉,或者將請(qǐng)求傳給下家。由于具體處理者持有對(duì)下家的引用,因此,如果需要,具體處理者可以訪問(wèn)下家。
Chain of Responsibility模式的實(shí)現(xiàn)
要實(shí)現(xiàn)Chain of Responsibility模式,需要滿足該模式的基本要件:
1,對(duì)象鏈的組織。需要將某任務(wù)的所有職責(zé)執(zhí)行對(duì)象以鏈的形式加以組織。
2,消息或請(qǐng)求的傳遞。將消息或請(qǐng)求沿著對(duì)象鏈傳遞,以讓處于對(duì)象鏈中的對(duì)象得到處理機(jī)會(huì)。
3,處于對(duì)象鏈中的對(duì)象的職責(zé)分配。不同的對(duì)象完成不同的職責(zé)。
4,任務(wù)的完成。處于對(duì)象鏈的末尾的對(duì)象結(jié)束任務(wù)并停止消息或請(qǐng)求的繼續(xù)傳遞。
Chain of Responsibility模式的優(yōu)優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
1,責(zé)任的分擔(dān)。每個(gè)類只需要處理自己該處理的工作(不該處理的傳遞給下一個(gè)對(duì)象完成),明確各類的責(zé)任范圍,符合類的最小封裝原則。
2,可以根據(jù)需要自由組合工作流程。如工作流程發(fā)生變化,可以通過(guò)重新分配對(duì)象鏈便可適應(yīng)新的工作流程。
3,類與類之間可以以松耦合的形式加以組織。
缺點(diǎn):
因?yàn)樘幚頃r(shí)以鏈的形式在對(duì)象間傳遞消息,根據(jù)實(shí)現(xiàn)方式不同,有可能會(huì)影響處理的速度。
例子:
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;
}
}
}