一、責任鏈(Chain of
Responsibility)模式的結構
在責任鏈模式裡,很多個物件由每一個對象對其下家的引用而連結起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的用戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響用戶端的情況下動態地重新組織鏈和分配責任。
如所示:
代碼如下 :
//Handler類
public
abstract class Handler {
protected Handler successor;
public abstract void handleRequest();
public void setSuccessor(Handler
successor){
this.successor = successor;
}
public Handler getSuccessor(){
return successor;
}
}
//ConcreteHandler類
public class
ConcreteHandler extends Handler {
@Override
public void handleRequest() {
if(getSuccessor()!=null){
System.out.println("the
request is passed to " + getSuccessor());
getSuccessor().handleRequest();
}else{
System.out.println("The
request is handler here");
}
}
}
//Client
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();
}
}
二、責任鏈模式在java中的應用
java1.0版的AWT事件處理機制
Java1.0版本中的AWT庫使用了責任鏈模式和命令模式處理GUI的事件。由於視窗構件往往位於容器構件內,因此,當事件發生在一個構件上時,此構件的事件處理器可以處理此事件,然後決定是否將事件向上級容器構件傳播。上級容器構件接到事件後,可以在此處理此事件,然後決定是否將事件再次向上級容器構件傳播,如此往複,直到事件到達頂層構件。
缺點:
(1)、AWT 1.0事件處理模型是基於繼承的。為了使一個程式能夠捕捉GUI事件並處理此事件,必須繼承此構件並且給其子類配備事件處理器,也就是置換掉action()方法或者handleEvent()方法。這不是應當提倡的做法:在一個物件導向的系統裡,經常使用的應當是委派關係,繼承關係不就當被濫用。
(2)、在一個複雜的GUI系統裡,這樣為所有事件的構件提供子類,會導致很多的子類,增加維護成本。
(3)、由於每一個事件都會沿著構件樹結構向上傳播,因此事件浮升機制會使得事件的處理變得較慢,這也是缺點之一。
DHTML中的事件處理
瀏覽器的DOM模型中的事件處理均採用責任鏈模式。
Netscape的事件模型:Netscape的事件處理機制叫做“事件捕捉(Event Capturing)”。在事件捕捉機制裡,一個事件是從DOM的最高一層向下傳播,也就是說,Windows對象是第一個接到事件上的,然後是document對象,如此往下。因此事件的產生對象反而是最後一個接到事件上的。
Internet Explorer的事件模型:當一個事件發生在Internet
Explorer所瀏覽的網頁中時,Internet Explorer會使用DHTML的“Event Bubbing”,即事件浮升機制處理此事件。Internet Explorer的DOM模型是HTML對象等級結構和事件處理機制。在DOM裡面,每一個HTML標識符都是一個DOM對象,而每一個DOM對象都可以產生事先定義好的幾個事件中的一個(或幾個)。這樣的一個事件首先發生在事件所屬的對象上,然後向上傳播,傳到此對象所屬的容器物件上。因此,事件浮動機制恰恰是事件捕捉機制的相反面。
另:Timer定時器
java.util.Timer類封裝了定時器所需的線程功能。與此類相應的,還有一個TimerTask類,封裝了當被定時的任務需要反覆發生時所需的線程功能。如所示:
Timer是TimerThread的子類,而TimerThread是Thread的實現,因此Timer是Thread的實現。同時TimerTask是Runnable的實現,從而也是一個線程。一個例子:
public class Reminder{
Timer timer;
public
Reminder(int seconds){
timer = new Timer();
timer.schedule(new
RemindTask(),seconds*1000);
}
class RemindTask extends TimerTask{
public void run(){
System.out.println(“Time’s
up”);
//結束timer線程
timer.cancel();
}
}
}
在每一個Timer對象的背後,都有一個背景線程,用來順序執行Timer的任務,這些任務應當迅速結束,不然就會霸佔timer用來執行任務的線程,從而延遲後面的任務。當所有的任務都完成後,timer的任務執行線程就會順利地結束並被java垃圾收集器所收集,只是垃圾收集的時間並不能預測。如果程式想要迅速地結束timer的任務執行線程,調用方法就應當調用timer的cancel()方法。Timer類是安全執行緒的,換言之,可以有多個線程共用同一個Timer對象,而不需要同步化。Timer類實際上是用Object.wait(long)方法實現定時的。