定義
使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免了請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系薄料。將這些對(duì)象連成一條鏈获诈,并沿著這條鏈傳遞該請(qǐng)求仍源,直到有對(duì)象處理它為止。
如果存在一種層次關(guān)系舔涎,通過(guò)責(zé)任鏈建立邏輯關(guān)系笼踩,較少因某種特定的if判斷。同時(shí)在客戶端修改責(zé)任層級(jí)關(guān)系就可以改變邏輯亡嫌,不用再邏輯代碼中修改嚎于;比較靈活。
不用責(zé)任鏈模式的處理方式:
public void test(int i, Request request){
if(i==1){
Handler1.response(request);
}else if(i == 2){
Handler2.response(request);
}else if(i == 3){
Handler3.response(request);
}else if(i == 4){
Handler4.response(request);
}else{
Handler5.response(request);
}
}
這種方法的優(yōu)點(diǎn)是非常直觀挟冠,簡(jiǎn)單明了于购,并且比較容易維護(hù),但是這種方法也存在著幾個(gè)比較令人頭疼的問(wèn)題:
代碼臃腫:實(shí)際應(yīng)用中的判定條件通常不是這么簡(jiǎn)單地判斷是否為1或者是否為2知染,也許需要復(fù)雜的計(jì)算肋僧,也許需要查詢數(shù)據(jù)庫(kù)等等,這就會(huì)有很多額外的代碼控淡,如果判斷條件再比較多嫌吠,那么這個(gè)if…else…語(yǔ)句基本上就沒(méi)法看了。
耦合度高:如果我們想繼續(xù)添加處理請(qǐng)求的類掺炭,那么就要繼續(xù)添加else if判定條件辫诅;另外,這個(gè)條件判定的順序也是寫(xiě)死的涧狮,如果想改變順序泥栖,那么也只能修改這個(gè)條件語(yǔ)句簇宽。
原理:
在上面的需求中,如果滿足條件1,則由Handler1來(lái)處理吧享,不滿足則向下傳遞魏割;如果滿足條件2,則由Handler2來(lái)處理钢颂,不滿足則繼續(xù)向下傳遞钞它,以此類推,直到條件結(jié)束殊鞭。把判定條件的部分放到處理類中遭垛,這就是責(zé)任連模式的原理。
角色
- 抽象處理類Handler:
抽象處理類中主要包含一個(gè)指向下一處理類的成員變量nextHandler和一個(gè)處理請(qǐng)求的方法handRequest操灿,handRequest方法的主要主要思想是锯仪,如果滿足處理的條件,則有本處理類來(lái)進(jìn)行處理趾盐,否則由nextHandler來(lái)處理庶喜。 - 具體處理類:
具體處理類主要是對(duì)具體的處理邏輯和處理的適用條件進(jìn)行實(shí)現(xiàn)。
代碼
抽象處理類
abstract class Handler {
private Handler nextHandler;
public final Response handleRequest(Request request){
Response response = null;
if(this.getHandlerLevel().above(request.getLevel())){
response = this.response(request);
}else{
if(this.nextHandler != null){
this.nextHandler.handleRequest(request);
}else{
System.out.println("-----沒(méi)有合適的處理器-----");
}
}
return response;
}
public void setNextHandler(Handler handler){
this.nextHandler = handler;
}
protected abstract Level getHandlerLevel();
public abstract Response response(Request request);
}
具體處理類1
class ConcreteHandler1 extends Handler {
protected Level getHandlerLevel() {
return new Level(1);
}
public Response response(Request request) {
System.out.println("-----請(qǐng)求由處理器1進(jìn)行處理-----");
return null;
}
}
具體處理類2
class ConcreteHandler2 extends Handler {
protected Level getHandlerLevel() {
return new Level(3);
}
public Response response(Request request) {
System.out.println("-----請(qǐng)求由處理器2進(jìn)行處理-----");
return null;
}
}
具體處理類3
class ConcreteHandler3 extends Handler {
protected Level getHandlerLevel() {
return new Level(5);
}
public Response response(Request request) {
System.out.println("-----請(qǐng)求由處理器3進(jìn)行處理-----");
return null;
}
}
其他
class Level {
private int level = 0;
public Level(int level){
this.level = level;
};
public boolean above(Level level){
if(this.level >= level.level){
return true;
}
return false;
}
}
class Request {
Level level;
public Request(Level level){
this.level = level;
}
public Level getLevel(){
return level;
}
}
class Response {
}
客戶端
public class Client {
public static void main(String[] args){
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
handler1.setNextHandler(handler2);
handler2.setNextHandler(handler3);
Response response = handler1.handleRequest(new Request(new Level(4)));
}
}
優(yōu)缺點(diǎn)
責(zé)任鏈模式與if…else…相比救鲤,他的耦合性要低一些久窟,因?yàn)樗褩l件判定都分散到了各個(gè)處理類中,并且這些處理類的優(yōu)先處理順序可以隨意設(shè)定本缠。責(zé)任鏈模式也有缺點(diǎn)斥扛,這與if…else…語(yǔ)句的缺點(diǎn)是一樣的,那就是在找到正確的處理類之前丹锹,所有的判定條件都要被執(zhí)行一遍稀颁,當(dāng)責(zé)任鏈比較長(zhǎng)時(shí),性能問(wèn)題比較嚴(yán)重楣黍。
適用場(chǎng)景
就像開(kāi)始的例子那樣峻村,假如使用if…else…語(yǔ)句來(lái)組織一個(gè)責(zé)任鏈時(shí)感到力不從心,代碼看上去很糟糕時(shí)锡凝,就可以使用責(zé)任鏈模式來(lái)進(jìn)行重構(gòu)粘昨。
總結(jié)
責(zé)任鏈模式其實(shí)就是一個(gè)靈活版的if…else…語(yǔ)句,它就是將這些判定條件的語(yǔ)句放到了各個(gè)處理類中窜锯,這樣做的優(yōu)點(diǎn)是比較靈活了张肾,但同樣也帶來(lái)了風(fēng)險(xiǎn),比如設(shè)置處理類前后關(guān)系時(shí)锚扎,一定要特別仔細(xì)吞瞪,搞對(duì)處理類前后邏輯的條件判斷關(guān)系,并且注意不要在鏈中出現(xiàn)循環(huán)引用的問(wèn)題驾孔。
Android中:
(1)ViewGroup時(shí)間分發(fā)(dispatchTouchEvent)
處理規(guī)則:如果時(shí)間被自己攔截芍秆,就自己處理惯疙,否則傳給子view;
(2)有序廣播(OrderedBroadcast)
普通廣播是異步的妖啥,發(fā)送后可以被所有的接收器接收到霉颠,而且無(wú)法確認(rèn)誰(shuí)先后接收到廣播;
而有序廣播是根據(jù)優(yōu)先級(jí)別來(lái)一次傳播的荆虱,中間可以被終止蒿偎;