12、責(zé)任鏈模式(設(shè)計(jì)模式筆記)

#一、概述

  • 設(shè)計(jì)模式
    • 創(chuàng)建型模式:關(guān)注對(duì)象的創(chuàng)建過程
    • 結(jié)構(gòu)型模式:關(guān)注對(duì)象和類的組織
    • 行為型模式:關(guān)注系統(tǒng)中對(duì)象之間的相互交互,研究系統(tǒng)在運(yùn)行時(shí)對(duì)象之間的相互通信和協(xié)作,進(jìn)一步明確對(duì)象的責(zé)任,共11種模式
  • 責(zé)任鏈模式(chain of responsibility
    定義:將能夠處理同一類請(qǐng)求的對(duì)象練成一條鏈,所提交的請(qǐng)求沿著鏈傳遞,鏈上的對(duì)象逐個(gè)判斷是否有能力處理該請(qǐng)求,如果能則處理,否則,傳遞給鏈上的下一個(gè)對(duì)象。

  • 場(chǎng)景:

    • 打牌時(shí),輪流出牌
    • 接力賽跑
    • 大學(xué)中,獎(jiǎng)學(xué)金審批
    • 公司中,公文審批

二、實(shí)例:請(qǐng)假條審批流程案例

LeaveRequest.java

package cn.itcast.day243.chainOfRespon;
//請(qǐng)假條:封裝請(qǐng)求的基本信息
public class LeaveRequest {
    private String empName;// 請(qǐng)假人
    private int leaveDays;// 請(qǐng)假天數(shù)
    private String reason;// 請(qǐng)假原因

    public LeaveRequest() {
    }

    public LeaveRequest(String empName, int leaveDays, String reason) {
        this.empName = empName;
        this.leaveDays = leaveDays;
        this.reason = reason;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public int getLeaveDays() {
        return leaveDays;
    }

    public void setLeaveDays(int leaveDays) {
        this.leaveDays = leaveDays;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }
}

說明:這就相當(dāng)于一個(gè)任務(wù)類。

Leader.java

package cn.itcast.day243.chainOfRespon;
//審批人:抽象類
public abstract class Leader {
    // 因?yàn)橹皇墙o子類使用,所以這里使用protected
    protected String name;// 領(lǐng)導(dǎo)名字
    protected Leader nextLeader;// 領(lǐng)導(dǎo)的上一級(jí)領(lǐng)導(dǎo)

    public Leader() {
    }

    public Leader(String name) {
        this.name = name;
    }

    public void setNextLeader(Leader nextLeader) {
        this.nextLeader = nextLeader;
    }
    
    public abstract void handleRequest(LeaveRequest request);//處理請(qǐng)求業(yè)務(wù)的核心方法
    
}

說明:這是一個(gè)處理器接口,因?yàn)槊總€(gè)審批對(duì)象有很多類似的地方。

Director.java

package cn.itcast.day243.chainOfRespon;
//主任
public class Director extends Leader {

    public Director(String name) {
        super(name);
    }

    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() < 3) {
            System.out.println("主任處理員工" + request.getEmpName() + "請(qǐng)假"
                    + request.getLeaveDays() + "天,理由是:" + request.getReason());
            System.out.println("主任" + this.name + "審批通過");
        } else {
            if (this.nextLeader != null) {
                this.nextLeader.handleRequest(request);
            }
        }
    }
}

Manager.java

package cn.itcast.day243.chainOfRespon;
//經(jīng)理
public class Manager extends Leader {

    public Manager(String name) {
        super(name);
    }

    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() < 10) {
            System.out.println("經(jīng)理處理員工" + request.getEmpName() + "請(qǐng)假"
                    + request.getLeaveDays() + "天,理由是:" + request.getReason());
            System.out.println("經(jīng)理" + this.name + "審批通過");
        } else {
            if (this.nextLeader != null) {
                this.nextLeader.handleRequest(request);
            }
        }
    }
}

GeneralManager.java

package cn.itcast.day243.chainOfRespon;
//總經(jīng)理
public class GeneralManager extends Leader {

    public GeneralManager(String name) {
        super(name);
    }

    public void handleRequest(LeaveRequest request) {
        if (request.getLeaveDays() < 30) {
            System.out.println("總經(jīng)理處理員工" + request.getEmpName() + "請(qǐng)假"
                    + request.getLeaveDays() + "天,理由是:" + request.getReason());
            System.out.println("總經(jīng)理" + this.name + "審批通過");
        } else {
            System.out.println("總經(jīng)理處理員工" + request.getEmpName() + "請(qǐng)假"
                    + request.getLeaveDays() + "天,理由是:" + request.getReason());
            System.out.println("總經(jīng)理" + this.name + "審批不通過");
        }
    }
}

說明:這是三個(gè)具體的處理器,分別處理不同等級(jí)但同類的事件。

Client.java

package cn.itcast.day243.chainOfRespon;
public class Client {
    public static void main(String[] args) {
        Leader l1 = new Director("張三");
        Leader l2 = new Manager("李四");
        Leader l3 = new GeneralManager("王五");
        
        //組織責(zé)任鏈對(duì)象的關(guān)系
        l1.setNextLeader(l2);
        l2.setNextLeader(l3);
        
        //處理請(qǐng)假操作
        LeaveRequest request = new LeaveRequest("Tom", 1, "回英國老家探親");
        l1.handleRequest(request);
    }
}

說明:可以看到各個(gè)具體的處理器的關(guān)系是我們?cè)谑褂玫臅r(shí)候才確定的,如果我們需要在中間添加其他的處理器類可以很方便的添加,只需要在使用的時(shí)候調(diào)整各個(gè)處理器的關(guān)系即可。

三、兩種責(zé)任鏈方式

  • 鏈表方式定義職責(zé)鏈(上面的案例)
  • 非鏈表方式實(shí)現(xiàn)職責(zé)鏈
    通過集合、數(shù)組生成職責(zé)鏈更加使用。實(shí)際上,很多項(xiàng)目中,每個(gè)具體Handler并不是由開發(fā)團(tuán)隊(duì)定義的,而是項(xiàng)目上線后由外部單位追加的,所以使用鏈表方式定義COR鏈就很困難。

四、開發(fā)中常見的場(chǎng)景

  • java中,異常機(jī)制就是一種責(zé)任鏈模式。一個(gè)try可以對(duì)應(yīng)多個(gè)catch,當(dāng)?shù)谝粋€(gè)catch不匹配類型,則自動(dòng)跳到第二個(gè)catch
  • js中,事件的冒泡和捕獲機(jī)制。java中,事件處理采用觀察者模式
  • servlet中,過濾器的鏈?zhǔn)教幚?/li>
  • struts2中,攔截器的調(diào)用也是典型的責(zé)任鏈模式
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 1 場(chǎng)景問題# 1.1 申請(qǐng)聚餐費(fèi)用## 來考慮這樣一個(gè)功能:申請(qǐng)聚餐費(fèi)用的管理。 很多公司都有這樣的福利,就是項(xiàng)...
    七寸知架構(gòu)閱讀 3,282評(píng)論 3 58
  • 一、設(shè)計(jì)模式的分類 總體來說設(shè)計(jì)模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者...
    RamboLI閱讀 833評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,696評(píng)論 18 399
  • http://jafeney.com/2016/03/06/20160306-gulp/
    forwardRain閱讀 206評(píng)論 0 0
  • 田生萬物成長(zhǎng)日記第十九天 微信號(hào):zspgy168 今天的主題讓寫寫父母,可是我卻不知道如何下筆。 作為遠(yuǎn)在外地的...
    紫色蒲公英168閱讀 245評(píng)論 1 0

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