定義
責(zé)任鏈模式是一種對象的行為模式。在責(zé)任鏈模式里,很多對象由每一個(gè)對象對其下家的引用而連接起來形成一條鏈。請求在這個(gè)鏈上傳遞,直到鏈上的某一個(gè)對象決定處理此請求。發(fā)出這個(gè)請求的客戶端并不知道鏈上的哪一個(gè)對象最終處理這個(gè)請求,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織和分配責(zé)任。——閻宏博士的《Java與模式》
責(zé)任鏈模式的結(jié)構(gòu)
角色
1、抽象處理者角色(Handler):定義出一個(gè)處理請求的接口。如果需要,接口可以定義 出一個(gè)方法以設(shè)定和返回對下家的引用。這個(gè)角色通常由一個(gè)Java抽象類或者Java接口實(shí)現(xiàn)。上圖中Handler類的聚合關(guān)系給出了具體子類對下家的引用,抽象方法handleRequest()規(guī)范了子類處理請求的操作。
2、具體處理者角色(ConcreteHandler):具體處理者接到請求后,可以選擇將請求處理掉,或者將請求傳給下家。由于具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
UML圖
代碼
public abstract class Handler {
protected Handler next;//持有后續(xù)的責(zé)任對象
/**
* 處理請求方法
* @return
*/
public abstract void handlerRequest();
public Handler getNext() {
return next;
}
public void setNext(Handler next) {
this.next = next;
}
}
public class HandlerA extends Handler {
/**
* 處理請求方法的具體實(shí)現(xiàn)(這是純責(zé)任鏈的實(shí)現(xiàn))
*/
public void handlerRequest(){
Handler next = this.getNext();
if(next==null){
System.out.println("A處理請求");
}else {
next.handlerRequest();
}
}
}
public class HandlerB extends Handler {
/**
* 處理請求方法的具體實(shí)現(xiàn)(這是純責(zé)任鏈的實(shí)現(xiàn))
*/
public void handlerRequest(){
Handler next = this.getNext();
if(next==null){
System.out.println("B處理請求");
}else {
next.handlerRequest();
}
}
}
public class Client {
public static void main(String[] args) {
//組裝責(zé)任鏈
Handler handlerA = new HandlerA();
Handler handlerB = new HandlerB();
handlerA.setNext(handlerB);
//提交請求
handlerA.handleRequest();
}
}
使用場景
考慮這樣一個(gè)場景:團(tuán)建費(fèi)用的審批流程。
不同級別的領(lǐng)導(dǎo)能夠?qū)徟淖畲蠼痤~各不相同,比如:項(xiàng)目經(jīng)理只能審批500元以內(nèi);部門經(jīng)理能審批1000元一捏的申請;總經(jīng)理可以審批任意額度的申請。
當(dāng)某人提出團(tuán)建費(fèi)用申請請求之后,該請求會經(jīng)由項(xiàng)目經(jīng)理、部門經(jīng)理、總經(jīng)理的審批,但是申請者是不知道最終是由誰審批的,每個(gè)領(lǐng)導(dǎo)會根據(jù)自己的責(zé)任范圍,來判斷是處理請求還是交給更高級別的領(lǐng)導(dǎo)處理,只要有領(lǐng)導(dǎo)處理了,流程就終止。
需要將每個(gè)領(lǐng)導(dǎo)的處理單獨(dú)出來,實(shí)現(xiàn)成單獨(dú)的職責(zé)處理對象,然后為他們提供一個(gè)公共的、抽象的膚質(zhì)則對象,按照先后鏈路進(jìn)行排列,或者按照客戶端的需求動態(tài)的組合責(zé)任鏈,以實(shí)現(xiàn)功能。
UML圖如下:
純的和不純的責(zé)任鏈
一個(gè)純的責(zé)任鏈模式要求一個(gè)具體的處理者對象只能在兩個(gè)行為中選擇一個(gè):一是承擔(dān)責(zé)任,而是把責(zé)任推給下家。不允許出現(xiàn)某一個(gè)具體處理者對象在承擔(dān)了一部分責(zé)任后又 把責(zé)任向下傳的情況。
在一個(gè)純的責(zé)任鏈模式里面,一個(gè)請求必須被某一個(gè)處理者對象所接收;在一個(gè)不純的責(zé)任鏈模式里面,一個(gè)請求可以最終不被任何接收端對象所接收。
純的責(zé)任鏈模式的實(shí)際例子很難找到,一般看到的例子均是不純的責(zé)任鏈模式的實(shí)現(xiàn)。有些人認(rèn)為不純的責(zé)任鏈根本不是責(zé)任鏈模式,這也許是有道理的。但是在實(shí)際的系統(tǒng)里,純的責(zé)任鏈很難找到。如果堅(jiān)持責(zé)任鏈不純便不是責(zé)任鏈模式,那么責(zé)任鏈模式便不會有太大意義了。
注:tomcat中的Filter就是使用了不純的責(zé)任鏈。