1.職責(zé)鏈模式簡(jiǎn)介
職責(zé)鏈(Chain of Responsibility)模式是是行為型(Behavioral)設(shè)計(jì)模式,是一種鏈?zhǔn)教幚碚?qǐng)求的設(shè)計(jì)模式于购,請(qǐng)求在鏈上傳遞妹懒,直到鏈上的有對(duì)象負(fù)責(zé)處理請(qǐng)求闹蒜。Servlet中Filter鏈、Spring MVC的Interceptor攔截器鏈揭芍,都是職責(zé)鏈的具體應(yīng)用胳搞。
職責(zé)鏈模式一共有二種角色:
(1) Handler(抽象處理者):它定義了處理請(qǐng)求的接口,還引用了下一個(gè)處理者称杨。
(2) ConcreteHandler(具體處理者):它是抽象處理者的子類肌毅,根據(jù)請(qǐng)求來(lái)判斷處理請(qǐng)求還是把請(qǐng)求傳遞給下一個(gè)具體處理者。
2. 職責(zé)鏈模式舉例
下面做一個(gè)經(jīng)費(fèi)申請(qǐng)的例子姑原,假設(shè)審批人共有三個(gè)悬而,分別是經(jīng)理、總監(jiān)锭汛、和總經(jīng)理笨奠;經(jīng)理審批500元以下的申請(qǐng),總監(jiān)審批1000元以下的申請(qǐng)唤殴,總經(jīng)理審批1000元以上的申請(qǐng)般婆。
序號(hào) | 類名 | 角色 | 說明 |
---|---|---|---|
1 | Handler | Handler | 抽象處理者 |
2 | Manager | ConcreteHandler | 具體處理者,經(jīng)理 |
3 | Director | ConcreteHandler | 具體處理者朵逝,總監(jiān) |
4 | GeneralManager | ConcreteHandler | 具體處理者蔚袍,總經(jīng)理 |
5 | ChainMain | 客戶端 | 演示調(diào)用,組裝責(zé)任鏈 |
1. 抽象處理者
/**
* 抽象處理者
*/
public abstract class Handler {
// 下一個(gè)處理者
private Handler nextHandler;
// 抽象的處理請(qǐng)求的方法
public abstract void handleRequest(int amount);
// 獲取下一個(gè)處理者
public Handler getNextHandler() {
return nextHandler;
}
// 設(shè)置下一個(gè)處理者
public void setNextHandler(Handler handler) {
this.nextHandler = handler;
}
}
2. 經(jīng)理
/**
* 經(jīng)理廉侧,審批500元以內(nèi)的經(jīng)費(fèi)
*/
public class Manager extends Handler {
@Override
public void handleRequest(int amount) {
if (amount < 500) {
System.out.println("我是經(jīng)理页响,批準(zhǔn)了經(jīng)費(fèi)申請(qǐng),金額是:" + amount);
} else {
Handler next = getNextHandler();
if (next != null) {
next.handleRequest(amount);
}
}
}
}
3. 總監(jiān)
/**
* 總監(jiān)段誊,審批1000元以內(nèi)的經(jīng)費(fèi)
*/
public class Director extends Handler{
@Override
public void handleRequest(int amount) {
if (amount < 1000) {
System.out.println("我是總監(jiān)闰蚕,批準(zhǔn)了經(jīng)費(fèi)申請(qǐng),金額是:" + amount);
} else {
Handler next = getNextHandler();
if (next != null) {
next.handleRequest(amount);
}
}
}
}
4. 總經(jīng)理
/**
* 總經(jīng)理连舍,審批大于1000元的經(jīng)費(fèi)没陡,如果超過5000元,就不批準(zhǔn)索赏。
*/
public class GeneralManager extends Handler {
@Override
public void handleRequest(int amount) {
if (amount >= 1000 && amount < 5000) {
System.out.println("我是總經(jīng)理盼玄,批準(zhǔn)了經(jīng)費(fèi)申請(qǐng),金額是:" + amount);
} else if (amount >= 5000) {
System.out.println("我是總經(jīng)理潜腻,駁回了經(jīng)費(fèi)申請(qǐng)埃儿,金額是:" + amount);
} else {
Handler next = getNextHandler();
if (next != null) {
next.handleRequest(amount);
}
}
}
}
5. 演示類
/**
* 客戶端演示
*/
public class ChainMain {
public static void main(String[] args) {
// 組裝責(zé)任鏈
Handler manager = new Manager();
Handler director = new Director();
Handler gm = new GeneralManager();
manager.setNextHandler(director);
director.setNextHandler(gm);
// Case 1
int fee = 823;
System.out.println("提交吃飯經(jīng)費(fèi)申請(qǐng),金額:" + fee);
manager.handleRequest(fee);
System.out.println("-----------------------");
// Case 2
fee = 8230;
System.out.println("提交團(tuán)隊(duì)建設(shè)經(jīng)費(fèi)申請(qǐng)融涣,金額:" + fee);
manager.handleRequest(fee);
}
}
結(jié)果輸出
提交吃飯經(jīng)費(fèi)申請(qǐng)童番,金額:823
我是總監(jiān),批準(zhǔn)了經(jīng)費(fèi)申請(qǐng)威鹿,金額是:823
-----------------------
提交團(tuán)隊(duì)建設(shè)經(jīng)費(fèi)申請(qǐng)剃斧,金額:8230
我是總經(jīng)理,駁回了經(jīng)費(fèi)申請(qǐng)忽你,金額是:8230
3. 總結(jié)
職責(zé)鏈分為純的和不純的兩種幼东。純的職責(zé)鏈中只有一個(gè)處理者會(huì)承擔(dān)起處理請(qǐng)求的責(zé)任,其余的處理者都只是轉(zhuǎn)發(fā)科雳;不純的職責(zé)鏈中根蟹,允許0到n個(gè)具體處理者處理請(qǐng)求。
職責(zé)鏈模式的優(yōu)點(diǎn)在于炸渡,請(qǐng)求方不需要知道是哪個(gè)Handler處理了請(qǐng)求娜亿,而且鏈中的Handler也不需要知道鏈的結(jié)構(gòu),帶來(lái)了系統(tǒng)的靈活性蚌堵。
職責(zé)鏈的缺點(diǎn)在于买决,由于沒有明確的Handler處理,可能導(dǎo)致請(qǐng)求無(wú)人處理吼畏;如果鏈很長(zhǎng)督赤,對(duì)于調(diào)試來(lái)說是不利的;如果建鏈不當(dāng)泻蚊,可能會(huì)出現(xiàn)死循環(huán)躲舌。
(完)