Java设计模式之行为型:责任链模式
背景:
????????學(xué)校規(guī)定參加校招的同學(xué)必須要請(qǐng)假,且要有相關(guān)人員的簽字,三天以下需輔導(dǎo)員簽字、三到七天需要系主任簽字,一個(gè)星期以上需要院長(zhǎng)簽字,更多的則需要校長(zhǎng)簽字!
?????????上圖將學(xué)生、輔導(dǎo)員、系主任、院長(zhǎng)、校長(zhǎng)組成了一個(gè)簡(jiǎn)單的鏈,在這個(gè)鏈上,學(xué)生是申請(qǐng)者,其余的都是請(qǐng)求處理者。對(duì)于這種將請(qǐng)求一級(jí)一級(jí)地往上傳遞直到請(qǐng)求被處理的設(shè)計(jì)模式就是職責(zé)鏈模式。
一、什么是責(zé)任鏈模式:
????????職責(zé)鏈可以將請(qǐng)求的處理者組織成一條鏈,并將請(qǐng)求沿著鏈傳遞,如果某個(gè)處理者能夠處理請(qǐng)求則處理,否則將該請(qǐng)求交由上級(jí)處理。客戶(hù)端只需將請(qǐng)求發(fā)送到職責(zé)鏈上,無(wú)須關(guān)注請(qǐng)求的處理細(xì)節(jié),通過(guò)職責(zé)鏈將請(qǐng)求的發(fā)送者和處理者解耦了,這也是職責(zé)鏈的設(shè)計(jì)動(dòng)機(jī)。????????
???????職責(zé)鏈模式可以簡(jiǎn)化對(duì)象間的相互連接,因?yàn)榭蛻?hù)端和處理者都沒(méi)有對(duì)方明確的信息,同時(shí)處理者也不知道職責(zé)鏈中的結(jié)構(gòu),處理者只需保存一個(gè)指向后續(xù)者的引用,而不需要保存所有候選者的引用。
? ? ? ? 另外職責(zé)鏈模式增加了系統(tǒng)的靈活性,我們可以任意增加或更改處理者,甚至更改處理者的順序,不過(guò)有可能會(huì)導(dǎo)致一個(gè)請(qǐng)求無(wú)論如何也得不到處理,因?yàn)樗赡鼙环胖迷阪溎┒恕?/p>
所以責(zé)任鏈模式有以下幾個(gè)優(yōu)點(diǎn):
- (1)降低耦合度,將請(qǐng)求的發(fā)送者和接收者解耦。反映在代碼上就是不需要在類(lèi)中寫(xiě)很多丑陋的 if….else 語(yǔ)句,如果用了職責(zé)鏈,相當(dāng)于我們面對(duì)一個(gè)黑箱,只需將請(qǐng)求遞交給其中一個(gè)處理者,然后讓黑箱內(nèi)部去負(fù)責(zé)傳遞就可以了。
- (2)簡(jiǎn)化了對(duì)象,使得對(duì)象不需要鏈的結(jié)構(gòu)。
- (3)增加系統(tǒng)的靈活性,通過(guò)改變鏈內(nèi)的成員或者調(diào)動(dòng)他們的次序,允許動(dòng)態(tài)地新增或者刪除處理者
- (4)增加新的請(qǐng)求處理類(lèi)很方便。
但是責(zé)任鏈模式也存在一些缺點(diǎn):
- (1)不能保證請(qǐng)求一定被成功處理
- (2)系統(tǒng)性能將受到一定影響,并且可能會(huì)造成循環(huán)調(diào)用。
- (3)可能不容易觀(guān)察運(yùn)行時(shí)的特征,而且在進(jìn)行代碼調(diào)試時(shí)不太方便,有礙于除錯(cuò)。
二、UML結(jié)構(gòu)圖:
- ?(1)Handler:抽象處理者,定義了一個(gè)處理請(qǐng)求的方法。所有的處理者都必須實(shí)現(xiàn)該抽象類(lèi)。?
- (2)ConcreteHandler:具體處理者,處理它所負(fù)責(zé)的請(qǐng)求,同時(shí)也可以訪(fǎng)問(wèn)它的后繼者,如果它能夠處理該請(qǐng)求則處理,否則將請(qǐng)求傳遞到它的后繼者。
- (3)Client: 客戶(hù)類(lèi)
下面是最典型的具體處理者類(lèi):
public class ConcreteHandler extends Handler {public void handleRequest(String request){if(請(qǐng)求request滿(mǎn)足條件){...... //處理請(qǐng)求;}else{this.successor.handleRequest(request); //轉(zhuǎn)發(fā)請(qǐng)求}} }三、代碼實(shí)現(xiàn):
我們將使用開(kāi)頭那個(gè)請(qǐng)假的實(shí)例。請(qǐng)假:3天以下輔導(dǎo)員簽字、3到5天系主任簽字、6到10天院長(zhǎng)簽字、11-15天校長(zhǎng)簽字、15天以上不允簽字。
首先是請(qǐng)假條:LeaveNode.java
public class LeaveNode {/** 請(qǐng)假天數(shù) **/private int number;/** 請(qǐng)假人 **/private String person;public LeaveNode(String person,int number){this.person = person;this.number = number;}public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}public String getPerson() {return person;}public void setPerson(String person) {this.person = person;} }抽象處理者:Leader.java
public abstract class Leader {/** 姓名 **/public String name;/** 后繼者 **/protected Leader successor;public Leader(String name){this.name = name;}public void setSuccessor(Leader successor) {this.successor = successor;}public abstract void handleRequest(LeaveNode LeaveNode); }四個(gè)具體處理者:輔導(dǎo)員:Instructor.java
public class Instructor extends Leader{public Instructor(String name){super(name);}public void handleRequest(LeaveNode LeaveNode) {if(LeaveNode.getNumber() <= 3){ //小于3天輔導(dǎo)員審批System.out.println("輔導(dǎo)員" + name + "審批" +LeaveNode.getPerson() + "同學(xué)的請(qǐng)假條,請(qǐng)假天數(shù)為" + LeaveNode.getNumber() + "天。");}else{ //否則傳遞給系主任if(this.successor != null){this.successor.handleRequest(LeaveNode);}}}}系主任: DepartmentHead.java
public class DepartmentHead extends Leader{public DepartmentHead(String name) {super(name);}public void handleRequest(LeaveNode LeaveNode) {if(LeaveNode.getNumber() <= 7){ //小于7天系主任審批System.out.println("系主任" + name + "審批" +LeaveNode.getPerson() + "同學(xué)的請(qǐng)假條,請(qǐng)假天數(shù)為" + LeaveNode.getNumber() + "天。");}else{ //否則傳遞給院長(zhǎng)if(this.successor != null){this.successor.handleRequest(LeaveNode);}}} }?院長(zhǎng):Dean.java
public class Dean extends Leader{public Dean(String name) {super(name);}public void handleRequest(LeaveNode LeaveNode) {if(LeaveNode.getNumber() <= 10){ //小于10天院長(zhǎng)審批System.out.println("院長(zhǎng)" + name + "審批" +LeaveNode.getPerson() + "同學(xué)的請(qǐng)假條,請(qǐng)假天數(shù)為" + LeaveNode.getNumber() + "天。");}else{ //否則傳遞給校長(zhǎng)if(this.successor != null){this.successor.handleRequest(LeaveNode);}}}}校長(zhǎng):President.java
public class President extends Leader{public President(String name) {super(name);}public void handleRequest(LeaveNode LeaveNode) {if(LeaveNode.getNumber() <= 15){ //小于15天校長(zhǎng)長(zhǎng)審批System.out.println("校長(zhǎng)" + name + "審批" +LeaveNode.getPerson() + "同學(xué)的請(qǐng)假條,請(qǐng)假天數(shù)為" + LeaveNode.getNumber() + "天。");}else{ //否則不允批準(zhǔn)System.out.println("請(qǐng)假天天超過(guò)15天,不批準(zhǔn)...");}}}?客戶(hù)端:Client.java
public class Client {public static void main(String[] args) {Leader instructor = new Instructor("陳毅"); //輔導(dǎo)員Leader departmentHead = new DepartmentHead("王明"); //系主任Leader dean = new Dean("張強(qiáng)"); //院長(zhǎng)Leader president = new President("王晗"); //校長(zhǎng)instructor.setSuccessor(departmentHead); //輔導(dǎo)員的后續(xù)者是系主任departmentHead.setSuccessor(dean); //系主任的后續(xù)者是院長(zhǎng)dean.setSuccessor(president); //院長(zhǎng)的后續(xù)者是校長(zhǎng)//請(qǐng)假3天的請(qǐng)假條LeaveNode leaveNode1 = new LeaveNode("張三", 3);instructor.handleRequest(leaveNode1); //請(qǐng)假9天的請(qǐng)假條LeaveNode leaveNode2 = new LeaveNode("李四", 9);instructor.handleRequest(leaveNode2);//請(qǐng)假15天的請(qǐng)假條LeaveNode leaveNode3 = new LeaveNode("王五", 15);instructor.handleRequest(leaveNode3);//請(qǐng)假20天的請(qǐng)假條LeaveNode leaveNode4 = new LeaveNode("趙六", 20);instructor.handleRequest(leaveNode4);} }運(yùn)行結(jié)果:
四、純的與不純的責(zé)任鏈模式:
(1)純的責(zé)任鏈模式要求處理者對(duì)象只能在兩個(gè)行為中選擇一個(gè):一是承擔(dān)責(zé)任,二是把責(zé)任推給下家,不允許出現(xiàn)某一個(gè)具體處理者對(duì)象在承擔(dān)了一部分責(zé)任后又把責(zé)任向下傳的情況。
(2)在純的責(zé)任鏈模式里面,請(qǐng)求必須被某一個(gè)處理者對(duì)象所接收;在不純的責(zé)任鏈模式里面,一個(gè)請(qǐng)求可以最終不被任何接收端對(duì)象所接收。
設(shè)計(jì)模式系列文章:
Java設(shè)計(jì)模式之創(chuàng)建型:工廠(chǎng)模式詳解(簡(jiǎn)單工廠(chǎng)+工廠(chǎng)方法+抽象工廠(chǎng))
Java設(shè)計(jì)模式之創(chuàng)建型:建造者模式
Java設(shè)計(jì)模式之創(chuàng)建型:單例模式
Java設(shè)計(jì)模式之創(chuàng)建型:原型模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:適配器模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:裝飾器模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:代理模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:橋接模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:外觀(guān)模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:組合模式
Java設(shè)計(jì)模式之結(jié)構(gòu)型:享元模式
Java設(shè)計(jì)模式之行為型:策略模式
Java設(shè)計(jì)模式之行為型:模板方法模式
Java設(shè)計(jì)模式之行為型:責(zé)任鏈模式
Java設(shè)計(jì)模式之行為型:觀(guān)察者模式
Java設(shè)計(jì)模式之行為型:訪(fǎng)問(wèn)者模式
Java設(shè)計(jì)模式之行為型:中介者模式
Java設(shè)計(jì)模式之行為型:命令模式
Java設(shè)計(jì)模式之行為型:狀態(tài)模式
Java設(shè)計(jì)模式之行為型:備忘錄模式
Java設(shè)計(jì)模式之行為型:迭代器模式
Java設(shè)計(jì)模式之行為型:解釋器模式
原博客鏈接:設(shè)計(jì)模式讀書(shū)筆記-----職責(zé)鏈模式_chenssy 的技術(shù)博客-CSDN博客
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Java设计模式之行为型:责任链模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java设计模式之行为型:迭代器模式
- 下一篇: Java设计模式之行为型:命令模式