Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 觀察者模式在Android開發場景中運用之通過Java源碼分析(一)

觀察者模式在Android開發場景中運用之通過Java源碼分析(一)

編輯:關於Android編程

對於觀察者,很多開發者並不陌生,在日常開發過程中,這也是一個非常常見的設計模式,尤其是Android小伙伴,很多人都知道broadcast就是一個典型的觀察者模式,還有最近很火的rxjava,響應式編程中,觀察者模式扮演著一個很重要的角色,但觀察者模式具體是怎麼樣運轉的,部分小伙伴就有點模糊了。

先從日常生活中一個例子開始說起,在看電視的過程中,我們經常看到一些抗日神劇中有這麼一個劇情,鬼子進村,在進村的過程中,總會有一些一些人通風報信,然後通知村裡的人能躲的躲,能藏的藏,能跑的跑,或者中路再搞個埋伏,抓到了以後是手撕還是其它方式處理,在此就先不做討論。。。其實這個過程中就是一個典型的觀察者模式,下面,我們先看一下手撕鬼子的UML。

這裡寫圖片描述

DevilsSubject.java

/**
 * 
 * created by zm on 2016-5-28
 * 繼承Observable,此類等同於上述UML的Devil(小鬼子),其它對號入座
 * 觀察鬼子是否來襲擊 
 *
 */
public class DevilsSubject extends Observable
{
    private String assault;

    public String isAssault() {
        return assault;
    }

    public void setAssault(String assault) {
        this.assault = assault;
        //可通過this.hasChanged()獲取是否發生改變,這裡我們統一設置成改變,以便測試
        this.setChanged();
        this.notifyObservers(assault);
    }
}

VillagerObserver.java

/**
 * 
 * created by zm on 2016-5-28
 * 
 * VillagerObserver(放哨的村民),觀察小鬼子行動
 *
 */
public class VillagerObserver implements Observer
{

    public void update(Observable o, Object obj) {
        // TODO Auto-generated method stub
        String assault = (String) obj;
        System.out.println(assault);
    }
}

Client.java

public class Client
{
    public static void main(String[] args) {
        VillagerObserver yes = new VillagerObserver();
        VillagerObserver no = new VillagerObserver();
        DevilsSubject devilsSubject = new DevilsSubject();
        //如果觀察者與集合中已有的觀察者不同,則向對象的觀察者集中添加此觀察者。
        devilsSubject.addObserver(yes);
        devilsSubject.addObserver(no);
        devilsSubject.setAssault("前方有一坨鬼子來了");
        devilsSubject.setAssault("鬼子見閻王了,在來村的路上就被村民手撕了");
        //返回 Observable 對象的觀察者數目
        System.out.println(devilsSubject.countObservers());
        System.out.println("................");
        devilsSubject.deleteObserver(yes);
        devilsSubject.setAssault("鬼子來了");
        System.out.println(devilsSubject.countObservers());
    }
}

運行的結果:

前方有一坨鬼子來了
前方有一坨鬼子來了
鬼子見閻王了,在來村的路上就被村民手撕了
鬼子見閻王了,在來村的路上就被村民手撕了
Observable對象的觀察者數目:2個
................
鬼子來了
Observable對象的觀察者數目:1個

下面是observable源碼

package java.util;

/**
 * This class represents an observable object, or "data"
 * in the model-view paradigm. It can be subclassed to represent an
 * object that the application wants to have observed.
 * 

* An observable object can have one or more observers. An observer * may be any object that implements interface Observer. After an * observable instance changes, an application calling the * Observable's notifyObservers method * causes all of its observers to be notified of the change by a call * to their update method. *

* The order in which notifications will be delivered is unspecified. * The default implementation provided in the Observable class will * notify Observers in the order in which they registered interest, but * subclasses may change this order, use no guaranteed order, deliver * notifications on separate threads, or may guarantee that their * subclass follows this order, as they choose. *

* Note that this notification mechanism has nothing to do with threads * and is completely separate from the wait and notify * mechanism of class Object. *

* When an observable object is newly created, its set of observers is * empty. Two observers are considered the same if and only if the * equals method returns true for them. * * @author Chris Warth * @see java.util.Observable#notifyObservers() * @see java.util.Observable#notifyObservers(java.lang.Object) * @see java.util.Observer * @see java.util.Observer#update(java.util.Observable, java.lang.Object) * @since JDK1.0 */ public class Observable { private boolean changed = false; private Vector obs; /** Construct an Observable with zero Observers. */ public Observable() { obs = new Vector<>(); } /** * Adds an observer to the set of observers for this object, provided * that it is not the same as some observer already in the set. * The order in which notifications will be delivered to multiple * observers is not specified. See the class comment. * * @param o an observer to be added. * @throws NullPointerException if the parameter o is null. */ public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } /** * Deletes an observer from the set of observers of this object. * Passing null to this method will have no effect. * @param o the observer to be deleted. */ public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } /** * If this object has changed, as indicated by the * hasChanged method, then notify all of its observers * and then call the clearChanged method to * indicate that this object has no longer changed. *

* Each observer has its update method called with two * arguments: this observable object and null. In other * words, this method is equivalent to: *

* notifyObservers(null)
* * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void notifyObservers() { notifyObservers(null); } /** * If this object has changed, as indicated by the * hasChanged method, then notify all of its observers * and then call the clearChanged method to indicate * that this object has no longer changed. *

* Each observer has its update method called with two * arguments: this observable object and the arg argument. * * @param arg any object. * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void notifyObservers(Object arg) { /* * a temporary array buffer, used as a snapshot of the state of * current Observers. */ Object[] arrLocal; synchronized (this) { /* We don't want the Observer doing callbacks into * arbitrary code while holding its own Monitor. * The code where we extract each Observable from * the Vector and store the state of the Observer * needs synchronization, but notifying observers * does not (should not). The worst result of any * potential race-condition here is that: * 1) a newly-added Observer will miss a * notification in progress * 2) a recently unregistered Observer will be * wrongly notified when it doesn't care */ if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } /** * Clears the observer list so that this object no longer has any observers. */ public synchronized void deleteObservers() { obs.removeAllElements(); } /** * Marks this Observable object as having been changed; the * hasChanged method will now return true. */ protected synchronized void setChanged() { changed = true; } /** * Indicates that this object has no longer changed, or that it has * already notified all of its observers of its most recent change, * so that the hasChanged method will now return false. * This method is called automatically by the * notifyObservers methods. * * @see java.util.Observable#notifyObservers() * @see java.util.Observable#notifyObservers(java.lang.Object) */ protected synchronized void clearChanged() { changed = false; } /** * Tests if this object has changed. * * @return true if and only if the setChanged * method has been called more recently than the * clearChanged method on this object; * false otherwise. * @see java.util.Observable#clearChanged() * @see java.util.Observable#setChanged() */ public synchronized boolean hasChanged() { return changed; } /** * Returns the number of observers of this Observable object. * * @return the number of observers of this object. */ public synchronized int countObservers() { return obs.size(); } }

再附上Observable的api
這裡寫圖片描述

根據源碼中最上部分的注釋,翻譯成中文後,大體的意思是此類是一個被觀察者。它可以派生子類來表示一個應用程序想要觀察的對象。一個可觀察到的對象(observable)可以有一個或多個觀察者(observer)。一個觀察者可以是任何實現接口的觀察者的對象。修改後可觀察到的實例,應用程序調用notifyObservers方法使所有的觀察者調用更新方法。通知的順序將是未指定的。請注意,這與線程通知機制無關,完全獨立於類對象的等待和通知機制。當一個可觀察的對象是新創建的,它的觀察是空的。當且僅當這個方法返回true,兩個觀察者是同步的。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPtS0wuvW0KOsxvC52Lz80NTX99PDtcS+zcrHdmVjdG9yus1jaGFuZ2Vko6zU2m9ic2VydmFibGXKtcD9u6+1xMqxuvKjrL7Ns/XKvLuvwcvSu7j2v9W1xHZlY3RvcqOsv8nS1M2ouf12ZWN0b3LM7bzTus3SxrP9dmVjdG9ystnX97rzo6y1sW9ic2VydmFibGW3osn6uMSx5Mqxo6zNqLn9Y2hhbmdlZMilxdC2z8rHt/HNqNaqo6zU2s7Sw8e1xMnPyvbKvsD9tPrC69bQyrnTw3NldENoYW5nZWQoKaOs1vfSqsrH0vLOqrXa0ru0zrzTyOu1xMqxuvKjrLK7u+HIpbX308NvYnNlcnZlcrXEdXBkYXRlt723qKOs0rK+zcrHY2hhbmdlZM6qZmFsc2WjrLWxY2hhbmdlZM6qZmFsc2XKsaOs1rG907TTbm90aWZ5T2JzZXJ2ZXJzt723qNbQcmV0dXJuo6zWu9PQY2hhbmdlZM6qdHJ1ZbXEyrG68rLFzajWqsui0MKjrMui0MLWrsewo6zW2NDCsNFjaGFuZ2VkuLPWtc6qZmFsc2WjrMzhyKHJz8r21LTC69bQtcS52Lz8tPrC68jnz8KjujwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); }

observer類

/**
 * A class can implement the Observer interface when it
 * wants to be informed of changes in observable objects.
 *
 * @author  Chris Warth
 * @see     java.util.Observable
 * @since   JDK1.0
 */
public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an Observable object's
     * notifyObservers method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the notifyObservers
     *                 method.
     */
    void update(Observable o, Object arg);
}

observer就是一個接口,裡面一個update方法,這個類沒太多需要解釋的,有點Java基礎的都可以明白。

現在一目了然了,Observer模式是一種行為模式,它的作用是當一個對象的狀態發生改變的時候,能夠自動通知其他關聯對象,自動刷新對象狀態。Observer模式提供給關聯對象一種同步通信的手段,使其某個對象與依賴它的其他對象之間保持狀態同步。

抽象主題角色(Subject)內部其實就是一個Vector,在addObserver的時候,就把需要的觀察者添加到Vector中。在deleteObserver的時候,就把傳進來的觀察者從容器中移除掉。主題角色又叫抽象被觀察者角色(observable),一般用一個抽象類或者接口來實現。

observable與observer是一種一對多的依賴關系,可以讓多個觀察者對象同時監聽某一個主題對象。觀察者模式有時被稱作發布/訂閱模式(Publish/Subscribe),對於這名稱很貼切的,就好比我們訂閱了報紙,每次報社新報紙出版發售的時候,就會根據訂閱的客戶一一發報紙,通知客戶閱讀。

ConcreteSubject:具體主題角色,將相關狀態存入具體觀察者對象。具體主題角色又叫具體被觀察者角色(ConcreteObservable)。

ConcreteObserver:具體觀察者角色,實現抽象觀察者角色(observer)所需要的更新接口,以便使自己狀態和主題狀態相協調。

這裡寫圖片描述系統能夠易於復用,應該選擇第耦合度的方案。減少對象之間的耦合度有利於系統的復用,在保證低耦合度的前提下並且能夠維持行動的協調一致,保證高度協作,觀察者模式是一種很好的設計方案。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved