標籤:設計模式 觀察者模式
觀察者模式定義:定義了對象之間的一對多的依賴,這樣一來,當一個對象發生改變狀態的時候,它的所有依賴者都會收到通知並自動更新。參考如:
觀察者設計模式也叫發布-訂閱模式。
也可以稱作:出版者+訂閱者 = 觀察者模式
在Android中觀察者模式的執行個體有:廣播機制,ContentObserver的註冊方式,一個是同步的觀察者模式,一個是非同步觀察者模式。
當兩個對象之間松耦合,它們依然可以互動,但是不清楚彼此的細節,觀察者提供了一種對象的設計,可以降低之間的耦合,避免對象的雙向依賴。
舉例:在Android中很多的Listener是觀察者模式,比如點擊事件的OnClickListener,就是為了避免對象的雙向依賴。
—-先來看看Java源碼中的觀察者模式:Observer觀察者介面:
package com.daming.java.observer;public interface Observer { void update(Observable observable, Object arg);}
對象Observable 類的實現
package com.daming.java.observer;import java.util.Vector;public class Observable { private boolean changed = false; private Vector obs; public Observable() { obs = new Vector(); } 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() { notifyObservers(null); } 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); } public synchronized void deleteObservers() { obs.removeAllElements(); } protected synchronized void setChanged() { changed = true; } protected synchronized void clearChanged() { changed = false; } public synchronized boolean hasChanged() { return changed; } /** * Returns the number of observers of this <tt>Observable</tt> object. * * @return the number of observers of this object. */ public synchronized int countObservers() { return obs.size(); }}
MyObserver 觀察者對象的實現
package com.daming.java.observer;public class MyObserver implements Observer{ @Override public void update(Observable observable, Object arg) { System.out.println("observable :" + observable + "arg :" + arg); }}
MyObserver2 觀察者對象的實現
package com.daming.java.observer;public class MyObserver2 implements Observer{ @Override public void update(Observable observable, Object arg) { System.out.println("observable2 :" + observable + "arg2 :" + arg); }}
TestObserver類的實現
package com.daming.java.observer;public class TestObserver { /** * @param args */ public static void main(String[] args) { Observable observable = new Observable(); MyObserver myObserver = new MyObserver(); MyObserver2 myObserver2 = new MyObserver2(); observable.addObserver(myObserver); observable.addObserver(myObserver2); observable.setChanged(); observable.notifyObservers(14); observable.setChanged(); observable.notifyObservers("I am daming"); }}
Log輸入結果:
observable2 :com.daming.java.observer.Observable@14318bbarg2 :14observable :com.daming.java.observer.Observable@14318bbarg :14observable2 :com.daming.java.observer.Observable@14318bbarg2 :I am damingobservable :com.daming.java.observer.Observable@14318bbarg :I am daming
Java源碼中上述代碼中用的是推模式,當然源碼中也有拉模式,即主動查詢的模式。拉模式就像廣播一樣,通過onReceive()方法拉起來一些動作的,還有像ContentObserver可以通過拉模式,當資料庫發生改變的時候,通過onChange()方法來調用一些操作。
—-接著我們來看看Android中非同步觀察者模式。
ContentObserver就是非同步觀察者模式,非同步觀察者有什麼好處呢?不阻塞觀察者的回調。在同步通知中會有阻塞問題,各個Observer的回應程式法是串列的,如果有一個observer耗時的話就會阻塞其他observer接收者了,這樣就有可能就會引起bug來,所以在設計的時候多考慮一些,是否考慮用非同步觀察者模式,讓並發處理快一些;我們通過一個簡單的demo來學習下非同步觀察者模式:
先來看看Observer,這個Android中是抽象的類
package cn.daming.observer.design;import android.os.Handler;import android.util.Log;public abstract class Observer { private Handler mHandler; public Observer(Handler handler) { mHandler = handler; } public void onChange() { } public final void dispatchChange() { Log.v("daming", "Observer dispatchChange is mHandler== null :" + (mHandler == null)); if (mHandler == null) { onChange(); } else { mHandler.post(new NotificationRunnable()); } } private final class NotificationRunnable implements Runnable { @Override public void run() { Log.v("daming", "NotificationRunnable dispatchChange is run ... "); Observer.this.onChange(); } }}
接著來看看ObserverService這個類的實現:
package cn.daming.observer.design;import java.util.ArrayList;import java.util.List;import android.util.Log;public class ObserverService { private int mState; private List<Observer> mObservers = new ArrayList<Observer>(); public final void registerObserver(Observer observer) { if (!mObservers.contains(observer)) { mObservers.add(observer); } } public final void unregisterObserver(Observer observer) { Log.v("daming", "ObserverService unregisterObserver :"); mObservers.remove(observer); } public void notifyChange() { for (Observer observer : mObservers) { observer.dispatchChange(); } } public int getState() { return mState; } public void setState(int state) { mState = state; notifyChange(); }}
最後我們來寫測試類別FirstActivity :
package cn.daming.observer.design;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import com.daming.designtraning.R;public class FirstActivity extends Activity { private ObserverService mObserverService; private Button mButton; private int mState = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.button); mObserverService = new ObserverService(); mObserverService.registerObserver(mFirstObserver); mObserverService.setState(++mState); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mObserverService.setState(++mState); } }); } @Override protected void onDestroy() { super.onDestroy(); mObserverService.unregisterObserver(mFirstObserver); } @Override protected void onResume() { super.onResume(); } @Override protected void onStop() { super.onStop(); } private Observer mFirstObserver = new Observer(new Handler()) { @Override public void onChange() { int state = mObserverService.getState(); Log.v("daming", "FirstObserver onChange is run state :" + state); } };}
總結:通過Handler來實現非同步觀察者模式,即構造Observer對象的時候傳一個Handler的對象,這樣在回調的時候,就用handler來發送非同步訊息在主線程上來執行相應的操作。
觀察者模式--Java設計模式