責(zé)任鏈模式

模式定義:

使多個對象都有計劃處理請求,從而避免請求的發(fā)送者和接受者之間的耦合關(guān)系。將
這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。

模式場景

  1. 打牌時,輪流出牌

  2. 接力賽跑

  3. 大學(xué)時,獎學(xué)金審核

模式結(jié)構(gòu)

Handler:定義職責(zé)的接口,通常在這里定義處理請求的方法,可以在這里實現(xiàn)后繼鏈。
ConcreteHandler:實現(xiàn)職責(zé)的類,在這個類中,實現(xiàn)對在職責(zé)范圍內(nèi)請求的處理,如果不處理,就繼續(xù)轉(zhuǎn)發(fā)請求給后繼者。
Client:職責(zé)鏈的客戶端,向鏈上的具體處理對象提交請求,讓職責(zé)鏈負責(zé)處理。

代碼實現(xiàn)

模擬請假審批流程:
提出請假申請
3內(nèi)天假期主任審批
超過3天總經(jīng)理審批
如果:其中需要一個副總經(jīng)理審批4~5天的假期,添加職責(zé)對象就行

普通實現(xiàn):使用if~else可以解決
現(xiàn)在使用責(zé)任鏈實現(xiàn)

UML圖

源碼

@Data
@AllArgsConstructor
public class LeaveNote {
    private String name;
    private String leaveReason;
    private int leaverDayNum;
}

public interface Handler {
    void handLeave(LeaveNote leaveNote);

    void setNextHandler(Handler h);
}

public class DirectorHandler implements Handler {
    private Handler nextHandler;

    public void handLeave(LeaveNote leaveNote) {
        if (leaveNote.getLeaverDayNum() <= 3) {
            System.out.println("主管同意" + leaveNote.getName() + "申請請假" + leaveNote.getLeaverDayNum() + "天,原因:" + leaveNote.getLeaveReason());
        } else {
            nextHandler.handLeave(leaveNote);
        }
    }

    public void setNextHandler(Handler h) {
        nextHandler = h;
    }
}

public class ManagerHandler implements Handler {
    private Handler nextHandler;

    public void handLeave(LeaveNote leaveNote) {
        System.out.println("總經(jīng)理同意" + leaveNote.getName() + "申請請假" + leaveNote.getLeaverDayNum() + "天,原因:" + leaveNote.getLeaveReason());
    }

    public void setNextHandler(Handler h) {
        nextHandler = h;
    }
}

public class ManagerHandler implements Handler {
    private Handler nextHandler;

    public void handLeave(LeaveNote leaveNote) {
        System.out.println("總經(jīng)理同意" + leaveNote.getName() + "申請請假" + leaveNote.getLeaverDayNum() + "天,原因:" + leaveNote.getLeaveReason());
    }

    public void setNextHandler(Handler h) {
        nextHandler = h;
    }
}

public class Client {

    public static void main(String[] args) {
        LeaveNote leaveNote = new LeaveNote("小米","肚子疼",8);
        DirectorHandler directorHandler = new DirectorHandler();
        ViceManagerHandler viceManagerHandler = new ViceManagerHandler();
        ManagerHandler managerHandler = new ManagerHandler();

        directorHandler.setNextHandler(viceManagerHandler);
        viceManagerHandler.setNextHandler(managerHandler);
        directorHandler.handLeave(leaveNote);
    }
}

模式的優(yōu)缺點

模式的優(yōu)點

  1. 請求者和接受者松散耦合

    在責(zé)任鏈模式中,請求者并不知道接受者是誰,也不知道具體如何處理
    請求者只負責(zé)向責(zé)任鏈發(fā)出請求就可以了,而每個職責(zé)對象也不用管請求者或者是其他的
    職責(zé)對象,只負責(zé)處理自己的部分,其他的就交給其他的職責(zé)對象去處理。也就是說,請求者和接受者
    是完全接偶的。

  2. 動態(tài)組合職責(zé)

    責(zé)任鏈模式會把功能處理分散到單獨的職責(zé)對象中,然后在使用的時候,就可以動態(tài)組合職責(zé)形成職責(zé)鏈,
    從而可以靈活地給對象分配職責(zé),也可以靈活地實現(xiàn)和改變對象的職責(zé)。

模式的缺點

  1. 產(chǎn)生許多細粒度對象

    責(zé)任鏈模式會把功能處理分散到單獨的職責(zé)對象中,也就是每個職責(zé)對象處理一個方面的功能,要把
    一個業(yè)務(wù)處理完,需要許多職責(zé)對象的組合,這樣會產(chǎn)生大量的細粒度職責(zé)對象。

  2. 不一定能被處理

    責(zé)任鏈模式的每個職責(zé)對象只負責(zé)處理自己處理的那部分,因此可能會出現(xiàn)某個請求,把整個責(zé)任鏈傳遞完也沒有職責(zé)對象處理它。這就需要在使用責(zé)任鏈的時候,需要提供默認的處理,并且注意構(gòu)建鏈的有效性。

思考

模式本質(zhì):分離職責(zé),動態(tài)組合。分離職責(zé)是前提,動態(tài)組合是精華所在。

開發(fā)中的應(yīng)用場景:

  1. Java中,異常機制就是一個責(zé)任鏈模式,一個try可以對應(yīng)多個catch,當(dāng)?shù)谝粋€catch不匹配類型,則自動跳到第二個catch.

  2. Servlet開發(fā)中,過濾器的鏈?zhǔn)教幚?/p>

  3. Struct2中,攔截器的調(diào)用也是典型的責(zé)任鏈模式

  4. JavaScript中,時間的冒泡和捕獲機制。Java語言中,事件的處理采用觀察者模式。

相關(guān)模式

  1. 責(zé)任鏈和組合模式
    兩個模式可以組合使用

  2. 責(zé)任鏈和裝飾者模式
    兩個模式相似,從某個角度講,可以相互模擬實現(xiàn)對方的功能。
    不同:一方面是目的不同,裝飾者模式是要實現(xiàn)透明的為對象添加功能,而責(zé)任鏈模式是要實現(xiàn)發(fā)送者和接受者節(jié)藕;
    另一方面,裝飾者是無限遞歸調(diào)用的,也可以任意多個對象來裝飾功能,但是責(zé)任鏈模式是有一個處理就結(jié)束(標(biāo)準(zhǔn)責(zé)任鏈模式)。

  3. 責(zé)任鏈和策略模式
    兩個模式可以組合使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容