觀察者模式

觀察者模式,是對象行爲型模式中的一種。觀察者模式的主旨是定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。

觀察者模式也可以稱爲發佈/訂閱模式,發佈者發佈信息,訂閱者獲取信息,訂閱了就能收到信息,沒訂閱就收不到信息。

觀察者模式提供了一種對象設計,讓主題和觀察者之間耦合度降得很低,爲什麼呢?關於觀察者的一切,主題只知道觀察者實現了Observer接口,並不需要觀察者具體的類是誰,做了什麼或者其他細節.

結構

觀察者模式的類結構關係如下:
這裏寫圖片描述

可以看到,該模式包含四個角色

抽象被觀察者角色:也就是一個抽象主題,它把所有對觀察者對象的引用保存在一個集合中,每個主題都可以有任意數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者角色。一般用一個抽象類和接口來實現。
抽象觀察者角色:爲所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
具體被觀察者角色:也就是一個具體的主題,在集體主題的內部狀態改變時,所有登記過的觀察者發出通知。
具體觀察者角色:實現抽象觀察者角色所需要的更新接口,一邊使本身的狀態與製圖的狀態相協調。

JDK對觀察者模式的支持

Java中已經提供了觀察者模式的實現,我們不需要再定義觀察者和目標接口(被觀察者),可以繼承Observable類實現被觀察者目標對象,實現Observer接口完成具體的觀察者對象。而且Observable類中的addObserver、deleteObserver、notifyObservers等方法已經幫我們考慮了線程同步的問題,這樣更安全。
Observer:


public synchronized void addObserver(Observer o) {
    if (o == null)
        throw new NullPointerException();
    if (!obs.contains(o)) {
        obs.addElement(o);
    }
}

public synchronized void deleteObserver(Observer o) {
    obs.removeElement(o);
}

public void notifyObservers(Object arg) {     
    Object[] arrLocal;
    synchronized (this) {
        //判斷標識狀態是否改變,默認爲false        
        if (!changed)
            return;
        arrLocal = obs.toArray();
        clearChanged();
    }
    for (int i = arrLocal.length-1; i>=0; i--)
        ((Observer)arrLocal[i]).update(this, arg);
}

/**
 * Marks this <tt>Observable</tt> object as having been changed; the
 * <tt>hasChanged</tt> method will now return <tt>true</tt>.
 */
protected synchronized void setChanged() {
    changed = true;
}

具體被觀察者:

public class Subject extends Observable {
    private int count=0;

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
        //改變標識狀態
        super.setChanged();
    }
}

具體觀察者:

public class ObserverImpl implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("update.......");
        //如果arg不爲null,被觀察者對象向觀察者推送主題的詳細信息
        System.out.println(arg);

        //從主題對象中"拉取"所需要的數據
        Subject sub=(Subject)o;
        System.out.println(sub.getCount());
    }
}

測試類:

public class ObserverDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();
        Observer observer = new ObserverImpl();
        subject.addObserver(observer);
        subject.setCount(5);
        subject.notifyObservers("calling");
    }
}

//輸出
update.......
calling
5

推模型和拉模型

觀察者模式根據其側重的功能還可以分爲推模型和拉模型
推模型:被觀察者對象向觀察者推送主題的詳細信息,不管觀察者是否需要,推送的信息通常是主題對象的全部或部分數據。一般這種模型的實現中,會把被觀察者對象中的全部或部分信息通過update的參數傳遞給觀察者[update(Object obj) ]。
拉模型:被觀察者在通知觀察者的時候,只傳遞少量信息。如果觀察者需要更具體的信息,由觀察者主動到被觀察者對象中獲取,相當於是觀察者從被觀察者對象中拉數據。一般這種模型的實現中,會把被觀察者對象自身通過update方法傳遞給觀察者[update(Observable observable ) ],這樣在觀察者需要獲取數據的時候,就可以通過這個引用來獲取了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章