Android開發中常見的設計模式(三)——觀察者模式

來源:互聯網
上載者:User

標籤:string   模式   sys   main   notify   gis   listen   over   內容   

先看下這個模式的定義。

定義對象間的一種一對多的依賴關係,當一個對象的狀態發送改變時,所有依賴於它的對象都能得到通知並被自動更新

先來講幾個情景。

  • 情景1:有一種簡訊服務,比如天氣預報服務,一旦你訂閱該服務,你只需月付型,付完費後,每天一旦有天氣資訊更新,它就會及時向你發送最新的天氣資訊。

  • 情景2:雜誌的訂閱,你只需向郵局訂閱雜誌,繳納一定的費用,當有新的雜誌時,郵局會自動將雜誌送至你預留的地址。

觀察上面兩個情景,有一個共同點,就是我們無需每時每刻關注我們感興趣的東西,我們只需做的就是訂閱感興趣的事物,比如天氣預報服務,雜誌等,一旦我們訂閱的事物發生變化,比如有新的天氣預報資訊,新的雜誌等,被訂閱的事物就會即時通知到訂閱者,即我們。而這些被訂閱的事物可以擁有多個訂閱者,也就是一對多的關係。當然,嚴格意義上講,這個一對多可以包含一對一,因為一對一是一對多的特例,沒有特殊說明,本文的一對多包含了一對一。

現在你反過頭來看看觀察者模式的定義,你是不是豁然開朗了。

然後我們看一下觀察者模式的幾個重要組成。

  • 觀察者,我們稱它為Observer,有時候我們也稱它為訂閱者,即Subscriber

  • 被觀察者,我們稱它為Observable,即可以被觀察的東西,有時候還會稱之為主題,即Subject

至於觀察者模式的具體實現,這裡帶帶大家實現一下情境一,其實java中提供了Observable類和Observer介面供我們快速的實現該模式,但是為了加深印象,我們不使用這兩個類。

情境1中我們感興趣的事情是天氣預報,於是,我們應該定義一個Weather實體類。

public class Weather {    private String description;    public Weather(String description) {        this.description = description;    }    public String getDescription() {        return description;    }    public void setDescription(String description) {        this.description = description;    }    @Override    public String toString() {        return "Weather{" +                "description=‘" + description + ‘\‘‘ +                ‘}‘;    }}

然後定義我們的被觀察者,我們想要這個被觀察者能夠通用,將其定義成泛型。內部應該暴露register和unregister方法供觀察者訂閱和取消訂閱,至於觀察者的儲存,直接用ArrayList即可,此外,當有主題內容發送改變時,會即時通知觀察者做出反應,因此應該暴露一個notifyObservers方法,以上方法的具體實現見如下代碼。

public class Observable<T> {    List<Observer<T>> mObservers = new ArrayList<Observer<T>>();    public void register(Observer<T> observer) {        if (observer == null) {            throw new NullPointerException("observer == null");        }        synchronized (this) {            if (!mObservers.contains(observer))                mObservers.add(observer);        }    }    public synchronized void unregister(Observer<T> observer) {        mObservers.remove(observer);    }    public void notifyObservers(T data) {        for (Observer<T> observer : mObservers) {            observer.onUpdate(this, data);        }    }}

而我們的觀察者,只需要實現一個觀察者的介面Observer,該介面也是泛型的。其定義如下。

public interface Observer<T> {    void onUpdate(Observable<T> observable,T data);}

一旦訂閱的主題發送變換就會回調該介面。

我們來使用一下,我們定義了一個天氣變換的主題,也就是被觀察者,還有兩個觀察者觀察天氣變換,一旦變換了,就列印出天氣資訊,注意一定要調用被觀察者的register進行註冊,否則會收不到變換資訊。而一旦不敢興趣了,直接調用unregister方法進行取消註冊即可

public class Main {    public static void main(String [] args){        Observable<Weather> observable=new Observable<Weather>();        Observer<Weather> observer1=new Observer<Weather>() {            @Override            public void onUpdate(Observable<Weather> observable, Weather data) {                System.out.println("觀察者1:"+data.toString());            }        };        Observer<Weather> observer2=new Observer<Weather>() {            @Override            public void onUpdate(Observable<Weather> observable, Weather data) {                System.out.println("觀察者2:"+data.toString());            }        };        observable.register(observer1);        observable.register(observer2);        Weather weather=new Weather("晴轉多雲");        observable.notifyObservers(weather);        Weather weather1=new Weather("多雲轉陰");        observable.notifyObservers(weather1);        observable.unregister(observer1);        Weather weather2=new Weather("颱風");        observable.notifyObservers(weather2);    }}

最後的輸出結果也是沒有什麼問題的,如下

觀察者1:Weather{description=’晴轉多雲’}觀察者2:Weather{description=’晴轉多雲’}觀察者1:Weather{description=’多雲轉陰’}觀察者2:Weather{description=’多雲轉陰’}觀察者2:Weather{description=’颱風’}

接下來我們看看觀察者模式在android中的應用。我們從最簡單的開始。還記得我們為一個Button設定點擊事件的代碼嗎。

Button btn=new Button(this);btn.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {        Log.e("TAG","click");    }});

其實嚴格意義上講,這個最多算是回調,但是我們可以將其看成是一對一的觀察者模式,即只有一個觀察者。

其實只要是set系列的設定監聽器的方法最多都只能算回調,但是有一些監聽器式add進去的,這種就是觀察者模式了,比如RecyclerView中的addOnScrollListener方法

private List<OnScrollListener> mScrollListeners;public void addOnScrollListener(OnScrollListener listener) {    if (mScrollListeners == null) {        mScrollListeners = new ArrayList<OnScrollListener>();    }    mScrollListeners.add(listener);}public void removeOnScrollListener(OnScrollListener listener) {    if (mScrollListeners != null) {        mScrollListeners.remove(listener);    }}public void clearOnScrollListeners() {    if (mScrollListeners != null) {        mScrollListeners.clear();    }}

類似的方法很多很多,都是add監聽器系列的方法,這裡也不再舉例。

還有一個地方就是Android的廣播機制,其本質也是觀察者模式,這裡為了簡單方便,直接拿本地廣播的代碼說明,即LocalBroadcastManager。

我們平時使用本地廣播主要就是下面四個方法

LocalBroadcastManager localBroadcastManager=LocalBroadcastManager.getInstance(this);localBroadcastManager.registerReceiver(BroadcastReceiver receiver, IntentFilter filter);localBroadcastManager.unregisterReceiver(BroadcastReceiver receiver);localBroadcastManager.sendBroadcast(Intent intent)

調用registerReceiver方法註冊廣播,調用unregisterReceiver方法取消註冊,之後直接使用sendBroadcast發送廣播,發送廣播之後,註冊的廣播會收到對應的廣播資訊,這就是典型的觀察者模式。

接下來我們看一下一些開源架構中的觀察者模式。一說到開源架構,你首先想到的應該是EventBus。沒錯,EventBus也是基於觀察者模式的。

觀察者模式的三個典型方法它都具有,即註冊,取消註冊,發送事件

EventBus.getDefault().register(Object subscriber);EventBus.getDefault().unregister(Object subscriber);EventBus.getDefault().post(Object event);

總之,在Android中觀察者模式還是被用得很頻繁的。

Android開發中常見的設計模式(三)——觀察者模式

相關文章

聯繫我們

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