責(zé)任鏈模式(Chain of Responsibility)

定義

責(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圖

責(zé)任鏈模式.png

代碼

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圖如下:


團(tuán)建費(fèi)審批UML圖.png

純的和不純的責(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é)任鏈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容