What:
責(zé)任鏈模式也叫職責(zé)鏈模式瞪醋。為了避免請求發(fā)送者與多個(gè)請求處理者耦合在一起爵政,將所有請求的處理者通過前一對象記住其下一個(gè)對象的引用而連成一條鏈矛物;當(dāng)有請求發(fā)生時(shí)霹琼,可將請求沿著這條鏈傳遞蓬抄,直到有對象處理它為止丰嘉。
Why:
優(yōu)點(diǎn):
1.降低耦合度。它將請求的發(fā)送者和接收者解耦嚷缭。
2.增強(qiáng)給對象指派職責(zé)的靈活性饮亏。通過改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序,允許動(dòng)態(tài)地新增或者刪除責(zé)任阅爽。
缺點(diǎn):
1.責(zé)任鏈太長或者每條鏈判斷處理的時(shí)間太長會(huì)影響性能路幸。特別是遞歸循環(huán)的時(shí)候
2.職責(zé)鏈建立的合理性要靠客戶端來保證,增加了客戶端的復(fù)雜性付翁,可能會(huì)由于職責(zé)鏈的錯(cuò)誤設(shè)置而導(dǎo)致系統(tǒng)出錯(cuò)简肴,如可能會(huì)造成循環(huán)調(diào)用。
3.不能保證每個(gè)請求一定被處理百侧。由于一個(gè)請求沒有明確的接收者砰识,所以不能保證它一定會(huì)被處理,該請求可能一直傳到鏈的末端都得不到處理佣渴。
Where:
1.有多個(gè)對象可以處理一個(gè)請求辫狼,哪個(gè)對象處理該請求由運(yùn)行時(shí)刻自動(dòng)確定。
2.可動(dòng)態(tài)指定一組對象處理請求观话,或添加新的處理者予借。
3.在不明確指定請求處理者的情況下,向多個(gè)處理者中的一個(gè)提交請求频蛔。
How:
職責(zé)鏈模式主要包含以下角色:
抽象處理者(Handler)角色: 定義一個(gè)處理請求的接口灵迫,包含抽象處理方法和一個(gè)后繼連接。
具體處理者(Concrete Handler)角色: 實(shí)現(xiàn)抽象處理者的處理方法晦溪,判斷能否處理本次請求瀑粥,如果可以處理請求則處理,否則將該請求轉(zhuǎn)給它的后繼者三圆。
客戶類(Client)角色: 創(chuàng)建處理鏈狞换,并向鏈頭的具體處理者對象提交請求避咆,它不關(guān)心處理細(xì)節(jié)和請求的傳遞過程。
示例:模擬程序員提交功能給測試人員修噪,測試人員覺得沒問題之后提交給技術(shù)總監(jiān)查库,技術(shù)總監(jiān)都覺得沒問題后才會(huì)通知老板,老板滿意之后就可以上線了黄琼。
ReviewPerson(抽象處理者角色):
public abstract class ReviewPerson {
protected ReviewPerson person;
abstract void handle(String program);
public ReviewPerson getPerson() {
return person;
}
public void setPerson(ReviewPerson person) {
this.person = person;
}
}
Tester樊销、CTO、Boss(具體處理者角色):
public class Tester extends ReviewPerson{
private final String NAME = "測試人員";
@Override
void handle(String program) {
if("沒有Bug的功能脏款!".equals(program)){
System.out.println(NAME + ":沒問題围苫,提交給技術(shù)總監(jiān)...");
getPerson().handle(program);
}else {
System.out.println(NAME + ":有Bug呀,再改改撤师!");
}
}
}
public class CTO extends ReviewPerson{
private final String NAME = "技術(shù)總監(jiān)";
@Override
void handle(String program) {
if("沒有Bug的功能剂府!".equals(program)){
System.out.println(NAME + ":沒問題,提交給老板...");
getPerson().handle(program);
}else {
System.out.println(NAME + ":有Bug呀剃盾,再改改腺占!");
}
}
}
public class Boss extends ReviewPerson{
private final String NAME = "老板";
@Override
void handle(String program) {
if("沒有Bug的功能!".equals(program)){
System.out.println(NAME + ":功能完成万俗,可以上線了湾笛!");
}else {
System.out.println(NAME + ":有Bug呀饮怯,再改改闰歪!");
}
}
}
Programmer(客戶類角色):
public class Programmer {
public static void main(String[] args) {
ReviewPerson tester = new Tester();
ReviewPerson cto = new CTO();
ReviewPerson boss = new Boss();
tester.setPerson(cto);
cto.setPerson(boss);
tester.handle("沒有Bug的功能!");
}
}
輸出結(jié)果:
測試人員:沒問題蓖墅,提交給技術(shù)總監(jiān)...
技術(shù)總監(jiān):沒問題库倘,提交給老板...
老板:功能完成,可以上線了论矾!
總結(jié)
我認(rèn)為責(zé)任鏈模式的好處在于客戶端不需要知道處理請求的內(nèi)部實(shí)現(xiàn)教翩,而是交給處理者內(nèi)部相互之間的調(diào)用。不過需要注意的是職責(zé)鏈不能過長贪壳,否則可能會(huì)導(dǎo)致性能下降饱亿,并且還需要保證請求一定會(huì)被處理,不要出現(xiàn)像“踢皮球”一樣闰靴,踢著踢著就沒下文了彪笼。