定義
為避免請(qǐng)求發(fā)送者與接收者耦合在一起镜盯,讓多個(gè)對(duì)象都有可能接收請(qǐng)求,將這些對(duì)象連接成一條鏈揩页,并且沿著這條鏈傳遞請(qǐng)求旷偿,直到有對(duì)象處理它為止。在這種模式中,通常每個(gè)接收者都包含對(duì)另一個(gè)接收者的引用萍程,如果一個(gè)對(duì)象不能處理該請(qǐng)求幢妄,那么它會(huì)把相同的請(qǐng)求傳給下一個(gè)接收者,依此類推茫负。
主要解決職責(zé)鏈上的處理者負(fù)責(zé)處理請(qǐng)求蕉鸳,客戶只需要將請(qǐng)求發(fā)送到職責(zé)鏈上即可,無須關(guān)心請(qǐng)求的處理細(xì)節(jié)和請(qǐng)求的傳遞忍法,所以職責(zé)鏈將請(qǐng)求的發(fā)送者和請(qǐng)求的處理者解耦了潮尝。
在責(zé)任鏈模式中發(fā)出請(qǐng)求的客戶端并不知道這當(dāng)中的哪個(gè)對(duì)象最終處理這個(gè)請(qǐng)求,這樣系統(tǒng)的更改可以在不影響客戶端的情況下動(dòng)態(tài)的重新組織和分配責(zé)任饿序。
使用場(chǎng)景
- 有多個(gè)對(duì)象可以處理同一個(gè)請(qǐng)求勉失,具體哪個(gè)對(duì)象處理該請(qǐng)求由運(yùn)行時(shí)刻自動(dòng)確定。
- 在不明確指定接收者的情況下原探,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求乱凿。
- 可動(dòng)態(tài)指定一組對(duì)象處理請(qǐng)求。
實(shí)現(xiàn)原理
Handler 里面聚合它自己咽弦,在 HandlerRequest 里判斷是否合適徒蟆,如果沒達(dá)到條件則向下傳遞,向誰傳遞之前 set 進(jìn)去离唬。
最重要的兩點(diǎn)后专,一個(gè)是你需要事先給每個(gè)具體管理者設(shè)置它的上司是哪個(gè)類划鸽,也就是設(shè)置后繼者输莺。另一點(diǎn)就是你需要在每個(gè)具體管理者處理請(qǐng)求時(shí),做出判斷裸诽,是可以處理這個(gè)請(qǐng)求嫂用,還是必須要“推卸責(zé)任”,轉(zhuǎn)移給后繼者去處理丈冬。
代碼實(shí)現(xiàn)
public abstract class Handler {
protected Handler successor;//繼任者
public Handler getSuccessor() {
return successor;
}
public void setSuccessor(Handler successor) {
this.successor = successor;
}
//處理請(qǐng)求
public void handleRequest(int request) {}
}
/**
* 當(dāng)請(qǐng)求數(shù)在0~10之間時(shí)有權(quán)處理嘱函,否則轉(zhuǎn)到下一位
*/
public class ConcreteHandlerA extends Handler {
public void handleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println(this.getClass() + " 處理請(qǐng)求 " + request);
}else if (successor != null) {
successor.handleRequest(request);
}
}
}
/**
* 當(dāng)請(qǐng)求數(shù)在10~20之間時(shí)有權(quán)處理,否則轉(zhuǎn)到下一位
*/
public class ConcreteHandlerB extends Handler {
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println(this.getClass() + " 處理請(qǐng)求 " + request);
}else if (successor != null) {
successor.handleRequest(request);
}
}
}
/**
* 當(dāng)請(qǐng)求數(shù)在20~30之間時(shí)有權(quán)處理埂蕊,否則轉(zhuǎn)到下一位
*/
public class ConcreteHandlerC extends Handler {
public void handleRequest(int request) {
if (request >= 20 && request < 30) {
System.out.println(this.getClass() + " 處理請(qǐng)求 " + request);
}else if (successor != null) {
successor.handleRequest(request);
}
}
}
/**
* 測(cè)試類
*/
public class ResponseChainPatternDemo {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
//設(shè)置責(zé)任鏈的前驅(qū)和后繼
handlerA.setSuccessor(handlerB);
handlerB.setSuccessor(handlerC);
int[] requests = {2,5,14,22,18,27,20};
for (int request : requests) {
handlerA.handleRequest(request);
}
}
}
運(yùn)行結(jié)果:
總結(jié)
優(yōu)點(diǎn)
1往弓、降低耦合度。它將請(qǐng)求的發(fā)送者和接收者解耦蓄氧。
2函似、簡(jiǎn)化了對(duì)象。使得對(duì)象不需要知道鏈的結(jié)構(gòu)喉童。
3撇寞、增強(qiáng)給對(duì)象指派職責(zé)的靈活性。通過改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序,允許動(dòng)態(tài)地新增或者刪除責(zé)任蔑担。
4牌废、增加新的請(qǐng)求處理類很方便。
缺點(diǎn)
1啤握、不能保證請(qǐng)求一定被接收鸟缕。
2、系統(tǒng)性能將受到一定影響排抬,可能會(huì)造成循環(huán)調(diào)用叁扫。
3、可能不容易觀察運(yùn)行時(shí)的特征畜埋,有礙于除錯(cuò)莫绣。