標籤:對象 遊戲 結構 類 java
Java模式開發之責任鏈模式
從擊鼓傳花談起
擊鼓傳花是一種熱鬧而又緊張的飲酒遊戲。在酒宴上賓客依次坐定位置,由一人擊鼓,擊鼓的地方與傳花的地方是分開的,以示公正。開始擊鼓時,花束就開始依次傳遞,鼓聲一落,如果花束在某人手中,則該人就得飲酒。
假比說,賈母、賈赦、賈政、賈寶玉和賈環是五個參加擊鼓傳花遊戲的傳花者,他們組成一個環鏈。擊鼓者將花傳給賈母,開始傳花遊戲。花由賈母傳給賈赦,由賈赦傳給賈政,由賈政傳給賈寶玉,又由賈寶玉傳給賈環,由賈環傳回給賈母,如此往複(見)。當鼓聲停止時,手中有花的人就得執行酒令。
擊鼓傳花便是責任鏈模式的應用。在責任鏈模式裡,很多的對象由每一個對象對其下家的引用而聯結起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的用戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響用戶端的情況下動態地重新組織鏈和分配責任。
責任鏈可能是一條直線、一個環鏈甚至一個樹結構的一部分。
責任鏈模式的結構
責任鏈模式是一種對象的行為模式,它所涉及到的角色如下:
第一、抽象處理者(Handler)角色、定義出一個處理請求的介面;如果需要,介面可以定義出一個方法,以返回對下家的引用。給出了一個示意性的類圖:
圖2、抽象處理者角色。
在圖中的積累關係給出了具體子類對下家的引用,抽象方法handleRequest()規範了子類處理請求的操作。
第二、具體處理者(ConcreteHandler)角色、處理接到請求後,可以選擇將請求處理掉,或者將請 求傳給下家。給出了一個示意性的類圖。
圖3、具體處理者角色。
中的示意性的具體處理者ConcreteHandler類只有handleRequest()一個方法。
責任鏈模式的靜態類結構可見:
圖4、責任鏈模式的類圖定義。
純的與不純的責任鏈模式
一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行為中選擇一個:一是承擔責任,二是把責任推給下家。不允許出現某一個具體處理者對象在承擔了一部分責任後又把責任向下傳的情況。
在一個純的責任鏈模式裡面,一個請求必須被某一個處理者對象所接受;在一個不純的責任鏈模式裡面,一個請求可以最終不被任何接受端對象所接受。
純的責任鏈模式的實際例子很難找到,一般看到的例子均是不純的責任鏈模式的實現。有些人認為不純的責任鏈根本不是責任鏈模式,這也許是有道理的;但是在實際的系統裡,純的責任鏈很難找到;如果堅持責任鏈不純便不是責任鏈模式,那麼責任鏈模式便不會有太大的意義了。
責任鏈模式要求鏈上所有的對象都繼承自一個共同的父類
在什麼情況下使用責任鏈模式
在下面的情況下使用責任鏈模式:
第一、系統已經有一個由處理者對象組成的鏈。這個鏈可能由複合模式給出,
第一、當有多於一個的處理者對象會處理一個請求,而且在事先並不知道到底由哪一個處理者對象處理一個請求。這個處理者對象是動態確定的。
第二、當系統想發出一個請求給多個處理者對象中的某一個,但是不明顯指定是哪一個處理者對象會處理此請求。
第三、當處理一個請求的處理者對象集合需要動態地指定時。
使用責任鏈模式的長處和短處
責任鏈模式減低了發出命令的對象和處理命令的對象之間的耦合,它允許多與一個的處理者對象根據自己的邏輯來決定哪一個處理者最終處理這個命令。換言之,發出命令的對象只是把命令傳給鏈結構的起始者,而不需要知道到底是鏈上的哪一個節點處理了這個命令。
顯然,這意味著在處理命令上,允許系統有更多的靈活性。哪一個對象最終處理一個命令可以因為由那些對象參加責任鏈、以及這些對象在責任鏈上的位置不同而有所不同。
責任鏈模式的實現
鏈結構的由來
值得指出的是,責任鏈模式並不建立出責任鏈。責任鏈的建立必須有系統的其它部分完成。
責任鏈模式減低了請求的發送端和接收端之間的耦合,使多個對象都有機會處理這個請求。一個鏈可以是一條線,一個樹,也可以是一個環。鏈的拓撲結構可以是單連通的或多連通的,責任鏈模式並不指定責任鏈的拓撲結構。但是責任鏈模式要求在同一個時間裡,命令只可以被傳給一個下家(或被處理掉);而不可以傳給多於一個下家。在下面的圖中,責任鏈是一個樹結構的一部分。
圖9、責任鏈是系統已有的樹結構的一部分。圖中有陰影的對象給出了一個可能的命令傳播路徑。
責任鏈的成員往往是一個更大的結構的一部分。比如在前面所討論的《紅樓夢》中擊鼓傳花的遊戲中,所有的成員都是賈府的成員。如果責任鏈的成員不存在,那麼為了使用責任鏈模式,就必須建立它們;責任鏈的具體處理者對象可以是同一個具體處理者類的執行個體。
在Java的1.0版的AWT事件處理模型裡,責任鏈便是視窗上的組件的容器等級結構。
在下面會談到的Internet Explorer的DHTML的DOM事件處理模型裡,責任鏈則是DOM等級結構本身。
命令的傳遞
在一個責任鏈上傳遞的可能不只有一個命令,而是數個命令。這些命令可以採取抽象化層、具體化層的多態性實現方式,見,從而可以將命令對象與責任鏈上的對象之間的責任分隔開,並將命令對象與傳播命令的對象分隔開。
圖10、多個命令在責任鏈上的傳播。
例子:
FilterChain管理整個Filter,並且自己也繼承Filter,這樣就可以附加其他FilterChain
public class FilterChain implements Filter {List<Filter> filters = new ArrayList<Filter>();private int index = 0;public FilterChain addFilter(Filter f) {filters.add(f);return this;}
public void doFilter(Request request, Response response, FilterChain chain) {if(index == filters.size()) return;Filter f = filters.get(index);index ++;f.doFilter(request, response, chain);}} public class HTMLFilter implements Filter { public void doFilter(Request request, Response response, FilterChain chain) {request.setRequestStr(request.getRequestStr().replace('<', '['));request.setRequestStr(request.getRequestStr().replace('>', ']') + "---HTMLFilter()");chain.doFilter(request, response, chain);response.setResponseStr(response.getResponseStr() + "---HTMLFilter()");} }
本文借鑒。
出處:yesky責任編輯:方舟
著作權聲明:歡迎轉載,希望在你轉載的同時,添加原文地址,謝謝配合
Java模式開發之責任鏈模式