編輯:關於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
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)所需要的更新接口,以便使自己狀態和主題狀態相協調。
系統能夠易於復用,應該選擇第耦合度的方案。減少對象之間的耦合度有利於系統的復用,在保證低耦合度的前提下並且能夠維持行動的協調一致,保證高度協作,觀察者模式是一種很好的設計方案。
第一次接觸樹形ListView是一年前,當時公司做的項目是一個企業的員工管理軟件,在展示員工時用到的,我花了大半天時間,才把樹形ListView搞明白,完成任務後就沒有然
前言:工欲善其事,必先利其器,工作一段時間後,對於以上十個字的感觸是最深的。剛參加工作的時候,並沒有對於要做的事情有著自己的理解,經常是上面分配了工作,自己就乖乖地跑去做
前言很多人開始安卓入門的學習,都會選擇Google官方的Android Studio作為開發工具,由於他跟之前的Eclipse不太一樣,所以出的問題也比較多。主要是導入的
12308全國汽車票網,是由中國道路運輸協會和全國站場工作委會合作共建,是一個服務於全國旅客公路客運出行的互聯網平台。現在有很多小伙伴都在計劃著怎麼回家過年