- 引入責任鏈模式
- 責任鏈模式的實例
- 責任鏈模式的分析
- 責任鏈模式的優勢
- 責任鏈模式的應用
引入責任鏈模式
責任鏈模式描述的就是如何推卸責任,說的簡潔點,就是踢皮球哈哈。舉個例子,有時候,出了某件事,我們去解決,找到A,結果A踢皮球,說這不關我的事,去找B解決,然后我們就去找B,結果B也說,這跟我沒關系,快去找C,就這樣,我們就被踢來踢去,這就是責任鏈模式的思想,在找到正確的人解決之前,我們被不斷的踢給一個有一個人,就是推卸責任。
上面的例子,可能有點貶義,但在實際編程中,有時候確實存在需要推卸責任的情況,,比如,當我們接受到一個請求時,當前的程序暫時無法處理這個請求,于是就需要把請求給別人去處理。如果是web開發人員,對此應該很熟悉,當服務器收到一個客戶端的請求時,首先會解析請求,action層不會處理請求,而是將請求的參數等信息進行簡單的解析處理,然后根據請求的內容信息等將請求具體轉發給service去處理。
當一個人被要求做一件事的時候,如果他自己可以做,那他就自己做了,如果他自己做不了,那就轉發給另一個人做,另一個人也是一樣,如果他自己可以做,就做,不可以做,就給別人做。。。。。。
這就是責任鏈模式的基本思想
責任鏈模式的實例
實例的類圖
Support是一個抽象類,他的核心方法support中,如果當前support可以解決,就解決,如果不行,就交給next去解決。
package ChainOfResponse;
public abstract class Support {
private String name;
private Support next;
public Support(String name) {
this.name = name;
}
public Support setNext(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);
}
}
public String toString() { // 顯示字符串
return "[" + name + "]";
}
protected abstract boolean resolve(Trouble trouble);
protected void done(Trouble trouble) {
System.out.println(trouble + " is resolved by " + this + ".");
}
protected void fail(Trouble trouble) { // 未解決
System.out.println(trouble + " cannot be resolved.");
}
}
然后我們實現幾個具體的support類
NoSupport類是一個永遠不解決問題的類
package ChainOfResponse;
public class NoSupport extends Support {
public NoSupport(String name) {
super(name);
}
@Override
protected boolean resolve(Trouble trouble) {
return false;
}
}
LimitSupport類,解決指定范圍內的問題
package ChainOfResponse;
public class LimitSupport extends Support {
private int limit;
public LimitSupport(String name, int limit) {
super(name);
this.limit = limit;
}
@Override
protected boolean resolve(Trouble trouble) {
if(trouble.getNumber() < limit)
return true;
return false;
}
}
OddSupport類,解決奇數的問題
package ChainOfResponse;
public class OddSupport extends Support {
public OddSupport(String name) {
super(name);
}
@Override
protected boolean resolve(Trouble trouble) {
if(trouble.getNumber() % 2 == 1)
return true;
return false;
}
}
package ChainOfResponse;
public class SpecialSupport extends Support {
private int number;
public SpecialSupport(String name, int number) {
super(name);
this.number = number;
}
@Override
protected boolean resolve(Trouble trouble) {
if(trouble.getNumber() == number)
return true;
return false;
}
}
,最后實現一個main類:
package ChainOfResponse;
public class Main {
public static void main(String[] args) {
Support alice = new NoSupport("Alice");
Support bob = new LimitSupport("Bob", 100);
Support charlie = new SpecialSupport("Charlie", 429);
Support diana = new LimitSupport("Diana", 200);
Support elmo = new OddSupport("Elmo");
Support fred = new LimitSupport("Fred", 300);
alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
for(int i=0;i<500;i+=33) {
alice.support(new Trouble(i));
}
}
}
Main類中定義了一個責任鏈,將幾個support對象連接在一起,組成了一條責任鏈,然后去處理問題
運行結果如下:
責任鏈模式的分析
首先,責任鏈模式中,存在著這么幾個角色:
Handler處理者
handler金額use定義了處理請求的接口,handler知道,下一個處理者是誰,如果自己無法處理請求,就轉給下一個處理者。
在實例中對應的是,support類和support方法concreteHandler(具體的處理者)
具體的處理者是處理請求的具體角色。
在此實例中,由NoSupport角色和其他幾個類扮演Client
請求者角色,就是向第一個具體的handler發送請求的角色,并連接好責任鏈,實例中對應的是main類的main方法。
責任鏈模式的類圖如下:
責任鏈的作用
弱化了發出請求的人和處理請求的人之間的關系
發出請求的人只需要向第一個具體的處理者發送請求,然后就可以不用管了,處理者會在責任鏈上自己尋找處理的方法。
這樣就解耦了處理者和請求者之間的關系。
如果我們不采取責任鏈模式,那么請求者就必須要很清楚哪個處理者能處理它的請求,就必須對所有的處理者都有所了解,類似于上帝視角,然而在實際中,要求請求這了解這么多是不實際的可以動態的改變責任鏈
責任鏈還有的好處就是可以動態的改變責任,刪除或者添加或者改變順序。讓各個處理者專注于實現自己的職責
責任鏈模式同時還做到了處理者之間的解耦,處理者自己專注于自己的處理邏輯就好,不管其他處理者干什么。推卸責任也可能導致處理延遲
我們可以責任鏈模式需要在責任鏈上傳播責任,直至找到合適的處理對象。這樣提高了程序的靈活性,但同時也出現了處理的延遲,因為有一個尋找的過程。所以需要低延遲的情況下,就不應該使用責任鏈模式
責任鏈模式的應用
在視窗系統中,經常會使用到責任鏈模式,尤其是事件的處理,熟悉javascript開發的朋友,可能會知道,瀏覽器中的事件有冒泡機制,,就是事件的是向父控件傳播的,如果自己處理不了,就會傳播給父控件去處理。