#一、概述
- 設(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é)任鏈模式