Java_觀察者模式(Observable和Observer)

來源:互聯網
上載者:User
一、觀察者模式介紹

在Java中通過Observable類和Observer介面實現了觀察者模式。一個Observer對象監視著一個Observable對象的變化,當Observable對象發生變化時,Observer得到通知,就可以進行相應的工作。

如果畫面A是顯示資料庫裡面的資料,而畫面B修改了資料庫裡面的資料,那麼這時候畫面A就要重新Load。這時候就可以用到觀察者模式

二、觀察者模式實現方法

java.util.Observable中有兩個方法對Observer特別重要

①setChanged()方法

    /**     * Sets the changed flag for this {@code Observable}. After calling     * {@code setChanged()}, {@code hasChanged()} will return {@code true}.     */    protected void setChanged() {        changed = true;    }

②notifyObservers()方法 / notifyObservers(Object data)方法

    /**     * If {@code hasChanged()} returns {@code true}, calls the {@code update()}     * method for every observer in the list of observers using null as the     * argument. Afterwards, calls {@code clearChanged()}.     * <p>     * Equivalent to calling {@code notifyObservers(null)}.     */    public void notifyObservers() {        notifyObservers(null);    }    /**     * If {@code hasChanged()} returns {@code true}, calls the {@code update()}     * method for every Observer in the list of observers using the specified     * argument. Afterwards calls {@code clearChanged()}.     *     * @param data     *            the argument passed to {@code update()}.     */    @SuppressWarnings("unchecked")    public void notifyObservers(Object data) {        int size = 0;        Observer[] arrays = null;        synchronized (this) {            if (hasChanged()) {                clearChanged();                size = observers.size();                arrays = new Observer[size];                observers.toArray(arrays);            }        }        if (arrays != null) {            for (Observer observer : arrays) {                observer.update(this, data);            }        }    }

以上兩個方法十分重要

setChanged()方法
——

用來設定一個內部標誌位註明資料發生了變化

notifyObservers()方法
/ notifyObservers(Object data)方法 ——

通知所有的Observer資料發生了變化,這時所有的Observer會自動調用複寫好的update(Observable
observable, Object data)方法來做一些處理(比如說畫面資料的更新)。

我們可以看到通知Observer有兩個方法,一個無參,一個有參。那麼這個參數有什麼作用呢?

其中一個作用:現在我不想通知所有的Observer,而只想其中一個指定的Observer做一些處理,那麼就可以傳一個參數作為ID,然後在所有的Observer中判斷,每個Observer判斷只有接收到底參數ID是屬於自己的才做一些處理。

當然參數還有其他作用,我只是舉了個例子。

下面舉個例子加以說明:

import java.util.Observable;  /** * 被觀察者類 */    public class SimpleObservable extends Observable  {     private int data = 0;         public int getData(){          return data;     }         public void setData(int i){         if(this.data != i) {           this.data = i;           setChanged();            //只有在setChange()被調用後,notifyObservers()才會去調用update(),否則什麼都不幹。          notifyObservers();           }     }  }  

上面這個類是一個被觀察者類,它繼承了Observable類,表示這個類是可以被觀察的。

然後在setData()方法裡面,也就是資料改變的地方,來調用Observable類的setChanged()方法和notifyObservers()方法,表示資料已改變並通知所有的Observer調用它們的update()方法做一些處理。

注意:只有在setChange()被調用後,notifyObservers()才會去調用update(),否則什麼都不幹。

/** * 觀察者類 */      public class SimpleObserver implements Observer  {     public SimpleObserver(SimpleObservable simpleObservable){        simpleObservable.addObserver(this );     }         public void update(Observable observable ,Object data){  // data為任意對象,用於傳遞參數      System.out.println(“Data has changed to” + (SimpleObservable)observable.getData());     }  } 

通過產生被觀察者(SimpleObservable類)的執行個體,來調用addObserver(this)方法讓觀察者(SimpleObserver類)達到觀察被觀察者(SimpleObservable類)的目的。

然後還要複寫update()方法,做資料改變後的一些處理。

下面可以寫一個簡單的測試類別來測試一下

public class SimpleTest  {     public static void main(String[] args){        SimpleObservable doc = new SimpleObservable ();        SimpleObserver view = new SimpleObserver (doc);        doc.setData(1);        doc.setData(2);        doc.setData(2);        doc.setData(3);      }  } 

運行結果如下

Data has changed to 1 Data has changed to 2  //第二次setData(2)時由於沒有setChange,所以update沒被調用Data has changed to 3

下面介紹一個Observable類的其他一些屬性和方法

屬性 ——

// observers是一個List,儲存著所有要通知的observer。    List<Observer> observers = new ArrayList<Observer>();// changed是一個boolean型標誌位,標誌著資料是否改變了。boolean changed = false;

方法 ——

// 添加一個Observer到列表observers中public void addObserver(Observer observer) {    if (observer == null) {        throw new NullPointerException();    }    synchronized (this) {        if (!observers.contains(observer))            observers.add(observer);    }}// 從列表observers中刪除一個observerpublic synchronized void deleteObserver(Observer observer) {    observers.remove(observer);}// 清空列表observerspublic synchronized void deleteObservers() {    observers.clear();}// 返回列表observers中observer的個數public int countObservers() {    return observers.size();}// 重設資料改變標誌位為未改變protected void clearChanged() { changed = false;}// 將資料改變標誌位設定為改變protected void setChanged() {     changed = true;}// 判斷標誌位的值public boolean hasChanged() {     return changed;}// 通知所有observer(無參)public void notifyObservers() {    notifyObservers(null);}// 通知所有observer(有參)@SuppressWarnings("unchecked")public void notifyObservers(Object data) {     int size = 0;     Observer[] arrays = null;     synchronized (this) {         if (hasChanged()) {             clearChanged();             size = observers.size();            arrays = new Observer[size];             observers.toArray(arrays);         }     }     if (arrays != null) {         for (Observer observer : arrays) {             observer.update(this, data);         }     }}

注意:在Observer對象銷毀前一定要用deleteObserver將其從列表中刪除,也就是在onDestroy()方法中調用deleteObserver()方法。

不然因為還存在對象引用的關係,Observer對象不會被垃圾收集,造成記憶體流失,並且已死的Observer仍會被通知到,有可能造成意料外的錯誤,而且隨著列表越來越大,notifyObservers操作也會越來越慢。

下面2個工程是Observable與Observer的經典運用,是android實現的單指拖動放大圖片的操作

兩個例子:

http://download.csdn.net/detail/tianjf0514/4237628

http://download.csdn.net/download/tianjf0514/4237634

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.