1、前言數據結構
責任鏈(chain of responsibility)模式很像異常的捕獲和處理,當一個問題發生的時候,當前對象看一下本身是否可以處理,不能的話將問題拋給本身的上級去處理,可是要注意這裏的上級不必定指的是繼承關係的父類,這點和異常的處理是不同的。因此能夠這樣說,當問題不能解決的時候,將問題交給另外一個對象去處理,就這樣一直傳遞下去直至當前對象找不到下線了,處理結束。以下圖所示,處於同等層次的類都繼承自Support類,噹噹前對象不能處理的時候,會根據預先設定好的傳遞關係將問題交給下一我的,能夠說是「近水樓臺先得月」,就看有沒有能力了。咱們也能夠看做是你們在玩一個傳謎語猜謎底的小遊戲,按照座位的次序以及規定的順序傳遞,若是一我的能回答的上來遊戲就結束,不然繼續向下傳,若是全部人都回答不出來也會結束。這樣或許纔是責任鏈的本質,體現出了同等級的概念。this
2、代碼spa
Trouble 類:(數據結構)設計
package zyr.dp.cor; public class Trouble { private int number; public Trouble( int number){ this.number=number; } public int getNumber() { return number; } public String toString(){ return "問題編號:["+number+"]"; } }
Support類:(抽象類,使用了模板方法)code
package zyr.dp.cor; public abstract class Support { protected abstract boolean resolve(Trouble trouble); String name; Support next; public Support(String name){ this.name=name; } public String toString() { return "對象:<"+name+">"; } public Support setAndReturnNext(Support next){ this.next=next; return next; } public final void support(Trouble trouble){ if(resolve(trouble)){ done(trouble); }else if(next!=null){ next.support(trouble); }else{ fail(trouble); } } protected void fail(Trouble trouble) { System.out.println(this+"解決問題失敗,"+trouble); } protected void done(Trouble trouble) { System.out.println(this+"已經解決問題,"+trouble); } }
NoSupport 類:對象
package zyr.dp.cor; public class NoSupport extends Support { public NoSupport(String name) { super(name); } protected boolean resolve(Trouble trouble) { return false; } }
OddSupport 類:blog
package zyr.dp.cor; public class OddSupport extends Support { public OddSupport(String name) { super(name); } protected boolean resolve(Trouble trouble) { return (trouble.getNumber()%2) == 1 ? true : false; } }
SpecialSupport 類:繼承
package zyr.dp.cor; public class SpecialSupport extends Support { public int specialNumber; public SpecialSupport(String name,int specialNumber) { super(name); this.specialNumber= specialNumber; } protected boolean resolve(Trouble trouble) { return trouble.getNumber()==specialNumber ? true : false; } }
LimitSupport 類:遊戲
package zyr.dp.cor; public class LimitSupport extends Support { private int limit; public LimitSupport(String name,int limit) { super(name); this.limit=limit; } protected boolean resolve(Trouble trouble) { return trouble.getNumber()<=limit? true : false; } }
Main類:ci
package zyr.dp.cor; public class Main { public static void main(String[] args) { Support limitSupportLess = new LimitSupport("有限支持小",5); Support limitSupportMore = new LimitSupport("有限支持大",15); Support oddSupport = new OddSupport("奇數支持"); Support specialSupport = new SpecialSupport("特定支持",36); Support noSupport = new NoSupport("沒有支持"); limitSupportLess.setAndReturnNext(limitSupportMore).setAndReturnNext(oddSupport).setAndReturnNext(specialSupport).setAndReturnNext(noSupport); System.out.println("===<有限支持小>嘗試解決問題==="); for(int i=0;i<40;i++){ limitSupportLess.support(new Trouble(i)); } System.out.println("===<特定支持>嘗試解決問題==="); for(int i=0;i<40;i++){ specialSupport.support(new Trouble(i)); } } }
運行結果:
===<有限支持小>嘗試解決問題=== 對象:<有限支持小>已經解決問題,問題編號:[0] 對象:<有限支持小>已經解決問題,問題編號:[1] 對象:<有限支持小>已經解決問題,問題編號:[2] 對象:<有限支持小>已經解決問題,問題編號:[3] 對象:<有限支持小>已經解決問題,問題編號:[4] 對象:<有限支持小>已經解決問題,問題編號:[5] 對象:<有限支持大>已經解決問題,問題編號:[6] 對象:<有限支持大>已經解決問題,問題編號:[7] 對象:<有限支持大>已經解決問題,問題編號:[8] 對象:<有限支持大>已經解決問題,問題編號:[9] 對象:<有限支持大>已經解決問題,問題編號:[10] 對象:<有限支持大>已經解決問題,問題編號:[11] 對象:<有限支持大>已經解決問題,問題編號:[12] 對象:<有限支持大>已經解決問題,問題編號:[13] 對象:<有限支持大>已經解決問題,問題編號:[14] 對象:<有限支持大>已經解決問題,問題編號:[15] 對象:<沒有支持>解決問題失敗,問題編號:[16] 對象:<奇數支持>已經解決問題,問題編號:[17] 對象:<沒有支持>解決問題失敗,問題編號:[18] 對象:<奇數支持>已經解決問題,問題編號:[19] 對象:<沒有支持>解決問題失敗,問題編號:[20] 對象:<奇數支持>已經解決問題,問題編號:[21] 對象:<沒有支持>解決問題失敗,問題編號:[22] 對象:<奇數支持>已經解決問題,問題編號:[23] 對象:<沒有支持>解決問題失敗,問題編號:[24] 對象:<奇數支持>已經解決問題,問題編號:[25] 對象:<沒有支持>解決問題失敗,問題編號:[26] 對象:<奇數支持>已經解決問題,問題編號:[27] 對象:<沒有支持>解決問題失敗,問題編號:[28] 對象:<奇數支持>已經解決問題,問題編號:[29] 對象:<沒有支持>解決問題失敗,問題編號:[30] 對象:<奇數支持>已經解決問題,問題編號:[31] 對象:<沒有支持>解決問題失敗,問題編號:[32] 對象:<奇數支持>已經解決問題,問題編號:[33] 對象:<沒有支持>解決問題失敗,問題編號:[34] 對象:<奇數支持>已經解決問題,問題編號:[35] 對象:<特定支持>已經解決問題,問題編號:[36] 對象:<奇數支持>已經解決問題,問題編號:[37] 對象:<沒有支持>解決問題失敗,問題編號:[38] 對象:<奇數支持>已經解決問題,問題編號:[39] ===<特定支持>嘗試解決問題=== 對象:<沒有支持>解決問題失敗,問題編號:[0] 對象:<沒有支持>解決問題失敗,問題編號:[1] 對象:<沒有支持>解決問題失敗,問題編號:[2] 對象:<沒有支持>解決問題失敗,問題編號:[3] 對象:<沒有支持>解決問題失敗,問題編號:[4] 對象:<沒有支持>解決問題失敗,問題編號:[5] 對象:<沒有支持>解決問題失敗,問題編號:[6] 對象:<沒有支持>解決問題失敗,問題編號:[7] 對象:<沒有支持>解決問題失敗,問題編號:[8] 對象:<沒有支持>解決問題失敗,問題編號:[9] 對象:<沒有支持>解決問題失敗,問題編號:[10] 對象:<沒有支持>解決問題失敗,問題編號:[11] 對象:<沒有支持>解決問題失敗,問題編號:[12] 對象:<沒有支持>解決問題失敗,問題編號:[13] 對象:<沒有支持>解決問題失敗,問題編號:[14] 對象:<沒有支持>解決問題失敗,問題編號:[15] 對象:<沒有支持>解決問題失敗,問題編號:[16] 對象:<沒有支持>解決問題失敗,問題編號:[17] 對象:<沒有支持>解決問題失敗,問題編號:[18] 對象:<沒有支持>解決問題失敗,問題編號:[19] 對象:<沒有支持>解決問題失敗,問題編號:[20] 對象:<沒有支持>解決問題失敗,問題編號:[21] 對象:<沒有支持>解決問題失敗,問題編號:[22] 對象:<沒有支持>解決問題失敗,問題編號:[23] 對象:<沒有支持>解決問題失敗,問題編號:[24] 對象:<沒有支持>解決問題失敗,問題編號:[25] 對象:<沒有支持>解決問題失敗,問題編號:[26] 對象:<沒有支持>解決問題失敗,問題編號:[27] 對象:<沒有支持>解決問題失敗,問題編號:[28] 對象:<沒有支持>解決問題失敗,問題編號:[29] 對象:<沒有支持>解決問題失敗,問題編號:[30] 對象:<沒有支持>解決問題失敗,問題編號:[31] 對象:<沒有支持>解決問題失敗,問題編號:[32] 對象:<沒有支持>解決問題失敗,問題編號:[33] 對象:<沒有支持>解決問題失敗,問題編號:[34] 對象:<沒有支持>解決問題失敗,問題編號:[35] 對象:<特定支持>已經解決問題,問題編號:[36] 對象:<沒有支持>解決問題失敗,問題編號:[37] 對象:<沒有支持>解決問題失敗,問題編號:[38] 對象:<沒有支持>解決問題失敗,問題編號:[39]
咱們能夠看到同等級的對象,按照本身被添加的次序來安排,這點很是重要,在實際應用中,咱們都是將解答能力最弱的類放到最前面,而後一點點增強,這樣可使得解答能力比較弱的類有機會去解答,正如咱們的例子,若是讓解答能力強的類直接去處理問題,可以處理就不回傳給下一個了,固然咱們也看到這裏面有的類能力有限,有的類和其餘類的能力有重疊部分,固然也有全部類都解決不了的問題。
經過責任鏈,咱們能夠將問題與處理問題的對象分離出來,特別適合用於不知道發生的問題究竟是什麼(有不少選擇)可是又必須處理的狀況(按照每一個選擇狀況設計相應的處理類),這樣就弱化了請求問題的人和回答問題的人的關係,若是不得不讓發出請求的人知道處理請求的人,這樣就不利於代碼的複用,由於須要在請求問題的對象之中調用處理請求的對象,而使用責任鏈模式就能很好的規避這一點,便於將這部分代碼獨立出來,當作組件使用,符合開閉原則。
一樣的咱們看到在責任鏈中使用了模板方法,在父類中抽象的定義了將要處理的流程,使得擴充起來很是方便,修改起來也很方便。利用委託的思想,不過此次是本身使用本身,經過責任鏈,其實就是一個鏈表,來處理問題是很是好的一種思想。能夠動態地修改責任鏈,同時也使得每一個責任鏈上的對象能夠專一於本身的問題,這樣思路清晰,便於擴展,可是使用責任鏈模式由於不斷地調用可以處理某個問題的對象(遍歷鏈表)和直接就能知道誰去處理的方式相比確定會出現延遲,這就須要一個取捨了。
最後,咱們要注意,resolve()的屬性是protected,這樣作的好處是可讓同一個包或者子類使用該方法,而不會讓其餘包的類使用,由於解決問題的方法就應該是子類使用的,這樣可使得該方法不被誤用。而將失敗和成功方法設爲protected,也是可讓子類去繼承和修改,而不讓其餘包中的類使用,對於support()方法就是可讓其餘包使用的,所以使用public,這一點能夠看出寫代碼的嚴謹度。
3、總結
責任鏈使用了模板方法和委託的思想構建了一個鏈表,經過遍歷鏈表來一個個詢問鏈表中的每個節點誰能夠處理某件事情,若是某個節點可以勝任,則直接處理,不然繼續向下傳遞,若是都不能處理next==null,則處理結束。責任鏈會形成處理的時延,可是可以解耦合,提升可擴展性,使得處理方法的類更專一於處理把本身的事情,便於擴展和改變處理的優先級,應用也很是的普遍。