設計模式——觀察者模式(Oberserver Pattern)

來源:互聯網
上載者:User

 設計模式------觀察者模式(Oberserver Pattern)


    定義:觀察者模式-在對象之間定義一對多的依賴。這樣以來,一個對象改變狀態時,依賴它的對象都會收到通知,並自動更新。

    OO設計的的思想裡,我們強調,我們的設計總是在為對象之間的互動的松耦合而努力。觀察者模式,正是在一對多的依賴中,尋找一種松耦合的實現方式。我們在日常生活中,經常會遇到這種情況,就是某個對象擁有某些狀態,而其它對象都需要使用這些狀態,從而執行某些行為。比如,在一個資料控制中心,有一個裝置來負責採集資料,並把資料即時的告知其它的部分,這些部門需要利用這些資料。因此,這就是一個一對多的依賴關係。假設我們以衛星控制系統來描述這個模式。

    假設系統的行為為:有一個資料擷取中心,負責擷取衛星的即時資料:經度,緯度,飛行時常。

資料擷取中西負責把及時採集到的資料通知其它部門,假設有兩個部門,一個負責即時顯示衛星的目前狀態,另外一個部門,負責通過接收到的資料進行計算,並輸出下一步的控制訊號。並且,該系統還不夠完善,可能會增加新的部門,該部門也需要利用衛星的即時資料,做其它的工作。

   根據以上的系統需求,我們可以知道,這是一個一對多的關係,並且,需要系統有很好的擴充性,即系統對象之間的耦合性要小。那我們怎麼來實現呢?

   系統有一個資料擷取中心,我們需要來設計一個類來描述這個資料擷取中心,假設叫做SatelliteData,

那麼顯示部門也用一個類DisplayBoard類以及計算部門也用一個類Calculate來描述。類SatelliteData定義如下所示:

class SatelliteData

{

 float longitude;

 float latitude;

 float timeLast;

 public float getLongitude()

{

 ……

}

public float getLatitude()

{

……

}

public float getTimeLast()

{

……

}

public setChange()

{

longitude=getLongitude();

latitude=getLatitude();

timeLast=getTimeLast();

displayBoard.update(longitudu,latitude,timeLast);

calculate.update(longitudu,latitude,timeLast);

}

}

   其中displayBoard是類DisplayBoard的對象,calculate是Calculate的對象。我們來看看這段代碼,實際上違背了我們在策略模式中一再強調的面向介面編程的思想,紅色部分的代碼是面向實現的,針對一個個的具體需要用到這些狀態的對象,發送通知。這樣,如果再增加新的使用對象,那就需要修改SatelliteDate類的代碼,並且,這樣造成的耦合性很大。

   那我們用觀察者模式如何來解決這個問題呢?觀察者模式定義了一對多的依賴,其中“一”被稱作主題,而“多”被稱作觀察者。觀察者通過註冊的方式來訂閱主題,當不需要的時候,再通過主題取消訂閱。這樣,多個觀察者通過訂閱的方式共用主題裡的內容。當主題內容改變的時候,需要動態通知觀察者,以便他們即使做出響應。

   在觀察者模式中,主題實現了Subject 介面,Subject介面主要定義了三個方法,即註冊觀察者,通知觀察者目前狀態以及刪除某個觀察者。

  定義如下:

  interface Subject

  {

   public void registerOberserver(Oberserver o);

   public void notifyOberservers(Oberserver o);

   public void deleteOberserver(Oberserver o); 

  }

在各個方法的參數中,Oberserver是觀察者介面,具體的觀察者實現該介面,這樣,在這裡,我們體現了面向介面編程的思想。

觀察者對象需要實現Oberserber介面,這個介面主要定義了更新的方法,update();這個方法主要是為了主題在更新狀態是調用,這樣在面向介面編程中,主題只關心介面實現的方法,具體由哪個類實現的,主題並不關心。我們來看相關的類圖.

由類圖可以看倒,SatelliteData類實現了Subject介面,而DisplayBoard類和Calculate類也分別實現了Oberserver介面,並且SatelliteData擁有多個註冊的觀察者,觀察者共用同一個主題。代碼如下:

//主題介面定義

interface Subject

{

public void registerOberserver(Oberserver o);

public void notifyOberservers(Oberserver o);

public void deleteOberserver(Oberserver o);

}

//觀察者介面定義

interface Oberserver

{

public void update(float longtitude,float latitude,float lastTime);

}

//類衛星資料定義

class SatelliteData

{

 float longitude;

 float latitude;

 float timeLast;

ArrayList oberservers;//註冊的觀察者列表

public SatelliteDate()

{

oberservers=new ArralyList();

}

 public float getLongitude()

{

 ……

}

public float getLatitude()

{

……

}

public float getTimeLast()

{

……

}

public setChange()

{

longitude=getLongitude();

latitude=getLatitude();

timeLast=getTimeLast();

notifyOberservers();

}

public void registerOberserver(Oberserver o)

{

oberservers.add(o);

}

public void deleteOberserver(Oberserver o)

{

int i=Oberservers.indexOf(o);

oberservers.remove(i);

}

public void notifyOberservers()

{

longtitude=getLongtitude();

latitude=getLatitude();

timeLast=getTimeLast();

 for(int i=0;i<oberservers.size();i++)

  {

   Oberserver oberserver=(Oberserver)oberservers.get(i);

   oberserber.update(longitude,latitude,timeLast);

}

}

}

//顯示部門類

class DisplayBoard  implements Oberserver

{

SatelliteDate data;

public DisplayData(SatelliteDate data)

{

this.data=data;

}

 public void update(float longtitude,float latitude,float timeLast)

{

 Syste.out.println("經度"+longtitude +"緯度:"+latitude+"持續時間長度"+timeLast);

 

}

//計算類

class Calculate implements Oberserver

{

 

SatelliteDate data;

public DisplayData(SatelliteDate data)

{

this.data=data;

}

 

 public void update(float longtitude,float latitude,float timeLast)

{

 //這是計算過程 

}

}

 

觀察者模式總結:

1,在物件導向設計過程中,依賴關係必不可少,我們經常在為對象間的松耦合設計而努力,這是我們進行OO設計的又一個準則,除了面向介面編程以外,還需要的是把是一個變為有一個(is a to has a)。

2,觀察者模式的適用範圍,就如定義所言,適用於一對多的依賴關係,一個對象狀態的改變影響所有其它對象,比如在銀行系統中,客戶帳戶的利息的計算是依賴於銀行的利率的,那銀行的利率的改變,必須由銀行象所有的客戶通知,從而利息的計算結果也會發生變化。這裡,銀行相當於一個主題,銀行客戶就是觀察者來訂閱這個主題。可以在這裡應用觀察者模式。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.