定義
為避免請求發(fā)送者與接收者耦合在一起,讓多個(gè)對象都有可能接收請求,將這些對象連接成一條鏈,并且沿著這條鏈傳遞請求,直到有對象處理它為止。在這種模式中,通常每個(gè)接收者都包含對另一個(gè)接收者的引用,如果一個(gè)對象不能處理該請求,那么它會把相同的請求傳給下一個(gè)接收者,依此類推。
主要解決職責(zé)鏈上的處理者負(fù)責(zé)處理請求,客戶只需要將請求發(fā)送到職責(zé)鏈上即可,無須關(guān)心請求的處理細(xì)節(jié)和請求的傳遞,所以職責(zé)鏈將請求的發(fā)送者和請求的處理者解耦了。
在責(zé)任鏈模式中發(fā)出請求的客戶端并不知道這當(dāng)中的哪個(gè)對象最終處理這個(gè)請求,這樣系統(tǒng)的更改可以在不影響客戶端的情況下動(dòng)態(tài)的重新組織和分配責(zé)任。
使用場景
- 有多個(gè)對象可以處理同一個(gè)請求,具體哪個(gè)對象處理該請求由運(yùn)行時(shí)刻自動(dòng)確定。
- 在不明確指定接收者的情況下,向多個(gè)對象中的一個(gè)提交一個(gè)請求。
- 可動(dòng)態(tài)指定一組對象處理請求。
實(shí)現(xiàn)原理
Handler 里面聚合它自己,在 HandlerRequest 里判斷是否合適,如果沒達(dá)到條件則向下傳遞,向誰傳遞之前 set 進(jìn)去。
最重要的兩點(diǎn),一個(gè)是你需要事先給每個(gè)具體管理者設(shè)置它的上司是哪個(gè)類,也就是設(shè)置后繼者。另一點(diǎn)就是你需要在每個(gè)具體管理者處理請求時(shí),做出判斷,是可以處理這個(gè)請求,還是必須要“推卸責(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;
}
//處理請求
public void handleRequest(int request) {}
}
/**
* 當(dā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() + " 處理請求 " + request);
}else if (successor != null) {
successor.handleRequest(request);
}
}
}
/**
* 當(dā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() + " 處理請求 " + request);
}else if (successor != null) {
successor.handleRequest(request);
}
}
}
/**
* 當(dā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() + " 處理請求 " + request);
}else if (successor != null) {
successor.handleRequest(request);
}
}
}
/**
* 測試類
*/
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、降低耦合度。它將請求的發(fā)送者和接收者解耦。
2、簡化了對象。使得對象不需要知道鏈的結(jié)構(gòu)。
3、增強(qiáng)給對象指派職責(zé)的靈活性。通過改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序,允許動(dòng)態(tài)地新增或者刪除責(zé)任。
4、增加新的請求處理類很方便。
缺點(diǎn)
1、不能保證請求一定被接收。
2、系統(tǒng)性能將受到一定影響,可能會造成循環(huán)調(diào)用。
3、可能不容易觀察運(yùn)行時(shí)的特征,有礙于除錯(cuò)。