責(zé)任鏈模式是一種對象的行為模式,。 在責(zé)任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈,。請求在這個鏈上傳遞,,直到鏈上的某一個對象決定處理此請求。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,,這使系統(tǒng)可以在不影響客戶端的情況下動態(tài)的重新組織鏈和分配責(zé)任,。
一、責(zé)任鏈模式的結(jié)構(gòu)
1,、責(zé)任鏈模式涉及的角色
抽象處理者角色(Handler):定義出一個處理請求的接口,。如果需要,接口可以定義出一個方法,,以設(shè)定和返回下家的引用,。這個角色通常由一個Java抽象類或Java接口實現(xiàn)。圖中的聚合關(guān)系給出了具體子類對下家的引用,,抽象方法handlerRequest()規(guī)范了子類處理請求的操作,。
具體處理者角色(ConcreteHandler):具體處理者接到請求后,可以選擇將請求處理掉,,或者將請求傳給下家。由于處理者持有下家引用,,因此,,如果需要,具體處理者可以訪問下家,。
抽象處理者角色
public abstract class Handler
{
protected Handler successor;//定義下家的引用
public abstract void handleRequest();//處理方法,,調(diào)用此方法處理請求
public void setSuccessor(Handler successor)//賦值方法,調(diào)用此方法設(shè)置下家
{
this.successor = successor;
}
public Handler getSuccessor()//取值方法,,得到下家對象
{
return successor;
}
}
具體處理者角色,,如果有下家,就將請求傳給下家,,否則就處理請求
public class ConcreteHandler extends Handler
{
public void handleRequest()
{
if (getSuccessor() != null)
{
System.out.println("The request is passed to " + getSuccessor());
getSuccessor().handleRequest();
}
else
{
System.out.println("The request is handled here.");
}
}
}
客戶端角色
public class Client
{
static private Handler handler1, handler2;
public static void main(String[] args)
{
handler1 = new ConcreteHandler();
handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
handler1.handleRequest();
}
}
客戶端創(chuàng)建了2個處理者對象,,并指定第一個處理者對象的下家是第2個處理者對象,,而第2個處理者對象沒有下家。然后客戶端將請求傳遞給第一個處理者對象,。
二,、純的與不純的責(zé)任鏈模式
一個純的責(zé)任鏈模式要求一個具體的處理者對象只能在2個行為中選擇一個:繼承責(zé)任或者把責(zé)任推給下家。不允許出現(xiàn)某一個具體處理者對象在承擔(dān)了一部分責(zé)任后又把責(zé)任向下傳的情況,。
在一個純的責(zé)任鏈模式里面,,一個請求必須被某一個處理者對象所接收器;在一個不純的責(zé)任鏈模式里面,,一個請求可以最終不被任何接收端對象所接收,。
純的責(zé)任鏈模式的例子很難找到,一般看到的例子都是不純的責(zé)任鏈模式的實現(xiàn),。
三,、責(zé)任鏈模式的實現(xiàn)
1、鏈結(jié)構(gòu)的由來
責(zé)任鏈模式并不創(chuàng)建出責(zé)任鏈,。責(zé)任鏈的創(chuàng)建必須由系統(tǒng)的其它部分創(chuàng)建出來
責(zé)任鏈模式減低了請求的發(fā)送端和接收端之間的耦合,,使多個對象有機會處理這個請求。一個鏈可以是一條線,,一個樹,,也可以是一個環(huán)。鏈的拓?fù)浣Y(jié)構(gòu)可以是單連通的或多連通的,,責(zé)任鏈模式并不指定責(zé)任鏈的拓?fù)浣Y(jié)構(gòu),。但是責(zé)任鏈模式要求在同一時間里,命令只可以被傳給一個下家(或被處理掉),,而不可以傳給多于一個下家,。
責(zé)任鏈的成員往往是一個更大結(jié)構(gòu)的一部分。如果責(zé)任鏈的成員不存在,,那么為了使用責(zé)任鏈模式,,就必須創(chuàng)建它們。責(zé)任鏈的具體處理者對象可以是同一個具體處理者的實例
在Internet Explorer的DHTML的DOM事件處理模型里,,責(zé)任鏈則是DOM等級結(jié)構(gòu)本身,。
2、命令的傳遞
在一個責(zé)任鏈上傳遞的可能不只有一個命令,,而是多個命令,。這些命令可以采取抽象化層、具體化層的多態(tài)性實現(xiàn)方式,,從而可以將命令對象于責(zé)任鏈上的對象之間的責(zé)任分隔開,,并將命令對象與傳播命令的對象分隔開。
如果責(zé)任鏈上的傳播命令只有一個、且是固定的命令,,那么這個命令不一定要對象化,。
四、DHTML中的事件處理
1,、Netscape的事件模型
Netscape的事件處理機制叫做“事件捕捉”(Event Capturing),。在事件捕捉機制里,一個事件是從DOM的最高層向下傳播,,window對象是第一個接到事件上的,,然后是document對象,如此向下,。因此事件的產(chǎn)生對象反而是最后一個接到事件上的,。
2、Internet Explorer的事件模型
當(dāng)一個事件發(fā)生在Internet Explorer所瀏覽的網(wǎng)頁中時,,Internet Explorer會使用DHTML的“Event Bubbling”,,即事件浮升機制處理事件。Internet Explorer的DOM模型是HTML對象等級結(jié)構(gòu)和事件處理機制,。在DOM里,,每一個HTML標(biāo)識符都是一個DOM對象,而每一個對象都可以產(chǎn)生事先定義好的幾個事件中的一個或幾個,。這樣的一個事件首先會發(fā)生在事件所屬的對象上,,然后向上傳播,傳到對象所屬的容器對象上,。因此,,事件浮升機制是事件捕捉機制的相反面。
在Event Bubbling機制里,,產(chǎn)生事件的對象首先會收到事件,。然后。事件會依照對象的等級結(jié)構(gòu)向上傳播,。
如果要阻止事件繼續(xù)向上傳播,,可以在事件鏈的任何一個節(jié)點上把cancelBubble性質(zhì)設(shè)置成True即可。
Internet Explorer瀏覽器幾乎為所有的HTML標(biāo)識符都提供了事件句柄,。因此Internet Explorer不用其它的方法來捕獲和釋放事件,。
<html xmlns="http://www./1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標(biāo)題文檔</title>
</head>
<script language="javascript">
document.onclick=click();
function click()
{
//return null;
alert('document event');
}
</script>
<body>
<form name="MyForm" onclick="alert('form event');">
<input type="button" value="click me" onclick=" alert(button event');"/>
</form>
</body>
</html>
這斷代碼顯示了個Internet Explorer的事件浮升機制,當(dāng)點擊button按鈕時,,按鈕先處理事件,然后傳給表單對象,,它也可以處理,。
|
|