您的位置:軟件測(cè)試 > 開源軟件測(cè)試 > 開源單元測(cè)試工具 > junit
JUNIT源碼探秘系列(下)
作者:網(wǎng)絡(luò)轉(zhuǎn)載 發(fā)布時(shí)間:[ 2013/4/16 14:34:04 ] 推薦標(biāo)簽:

JUNIT源碼探秘(五):Junit代碼分析之觀察者模式

JUnit源碼中實(shí)現(xiàn)支持不同的使用方式:swt、swing的UI方式和控制臺(tái)方式,對(duì)于這些不同的UI如何提供統(tǒng)一的接口供它們獲取測(cè)試過程的信息(比如出現(xiàn)的異常信息,測(cè)試成功,測(cè)試失敗的代碼行數(shù)等等)?我們?cè)囅胍幌逻@個(gè)場(chǎng)景,當(dāng)一個(gè)error或者fail產(chǎn)生的時(shí)候,測(cè)試能夠馬上通知這些UI客戶端:發(fā)生錯(cuò)誤了,發(fā)生了什么錯(cuò)誤,錯(cuò)誤是什么等等。顯而易見,這是一個(gè)訂閱-發(fā)布或者源-監(jiān)聽機(jī)制應(yīng)用的場(chǎng)景,應(yīng)當(dāng)使用觀察者模式。那么什么是觀察者模式呢?

為了便于理解觀察者模式,舉一個(gè)現(xiàn)實(shí)生活中的例子:在中國好聲音比賽過程其實(shí)是觀察者模式的好體現(xiàn),可以這樣說吳莫愁等上臺(tái)比賽者是一個(gè)個(gè)被觀察者,而劉歡、那英、楊坤等人是4個(gè)觀察者,被觀察者操作(唱歌)時(shí),觀察者們開始操作(評(píng)分),被觀察者唱歌是通知觀察者們進(jìn)行評(píng)分。

另外在第二季傳劉歡等人不在作為導(dǎo)師,當(dāng)然其中的歌手也會(huì)變化。由上面的例子可以產(chǎn)出,在觀察者模式中的角色主要有兩大類四個(gè)角色即:觀察者、被觀察者兩大類,四個(gè)角色即:觀察者接口類(導(dǎo)師)、觀察者具體實(shí)現(xiàn)類(具體導(dǎo)師,比如劉歡等)、被觀察者接口類(歌手或者演員)、具體被觀察者(吳莫愁等人)

根據(jù)以上的例子總結(jié)一下觀察者模式的組成角色:

抽象主題角色:把所有對(duì)觀察者對(duì)象的引用保存在一個(gè)集合中,每個(gè)抽象主題角色都可以有任意數(shù)量的觀察者。抽象主題提供一個(gè)接口,可以增加和刪除觀察者角色。一般用一個(gè)抽象類或接口來實(shí)現(xiàn)。這個(gè)映射到上面的例子是被觀察者接口類(歌手或者演員)

抽象觀察者角色:為所有具體的觀察者定義一個(gè)接口,在得到主題的通知時(shí)更新自己。 這個(gè)映射到上面的例子中的角色自然是觀察者接口類(導(dǎo)師)

具體主題角色:在具體主題內(nèi)部狀態(tài)改變時(shí),給所有登記過的觀察者發(fā)出通知。具體主題角色通常用一個(gè)子類實(shí)現(xiàn)。這個(gè)映射到上面的例子中的角色自然是被觀察者的實(shí)現(xiàn)類(即吳莫愁等人)

具體觀察者角色:該角色實(shí)現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題的狀態(tài)相協(xié)調(diào)。如果需要,具體觀察者角色可以保存一個(gè)指向具體主題角色的引用。通常用一個(gè)子類實(shí)現(xiàn)這個(gè)映射到上面的例子中的角色自然是觀察者具體實(shí)現(xiàn)類(具體導(dǎo)師,比如劉歡等)

再看看他們之間的關(guān)聯(lián)關(guān)系

Watcher及其子類維護(hù)一個(gè)觀察者列表,當(dāng)需要通知所有的Watched對(duì)象時(shí)調(diào)用notifyWatchers方法遍歷Watched集合,并調(diào)用它們的update方法更新。而具體的觀察者實(shí)現(xiàn)Watched接口(或者抽象類),提供具體的更新行為。

具體實(shí)現(xiàn)代碼如下:

抽象主題角色:

public interface Watched {

  public void addWatcher(Watcher wather);

  public void delWatcher(Watcher wather);

  public void notifyWatchers(String str);

 }

具體主題角色:

public class WatchedImpl implements Watched {

  List list = newArrayList();

  public void addWatcher(Watcher wather) {

     list.add(wather);

  }

  public void delWatcher(Watcher wather) {

     list.remove(wather);

  }

  public void notifyWatchers(String str) {

     for (Watcher wather : list) {

        wather.update(str);

     }

  }

抽象觀察者角色:

public interface Watcher {

  public void update(String str);

}

具體觀察者角色:

public class WatcherImpl implements Watcher{

  public void update(String str) {

     System.out.print(str);

  }

}

觀察者模式會(huì)達(dá)到如下效果:

1)     目標(biāo)和觀察者的抽象耦合,目標(biāo)僅僅與抽象層次的簡單接口Watcher松耦合,而沒有與具體的觀察者緊耦合

2)     支持廣播通信

3)     缺點(diǎn)是可能導(dǎo)致意外的更新,因?yàn)橐粋(gè)觀察者并不知道其他觀察者,它的更新行為也許將導(dǎo)致一連串不可預(yù)測(cè)的更新的行為

接著看下JUnit是怎么實(shí)現(xiàn)這個(gè)模式的。在junit.framework包中我們看到了一個(gè)Watcher觀察者接口——TestListener,代碼如下:

public interfaceTestListener {

   public void addError(Test test, Throwable t);

   public void addFailure(Test test, AssertionFailedError t);  

   public void endTest(Test test); 

   public void startTest(Test test);

}

上一頁1234567下一頁
軟件測(cè)試工具 | 聯(lián)系我們 | 投訴建議 | 誠聘英才 | 申請(qǐng)使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd