观察者模式定义:定义了对象之间的一对多的依赖,这样一来,当一个对象发生改变状态的时候,它的所有依赖者都会收到通知并自动更新。参考如下图:
观察者设计模式也叫发布-订阅模式。
也可以称作:出版者+订阅者 = 观察者模式
在Android中观察者模式的实例有:广播机制,ContentObserver的注册方式,一个是同步的观察者模式,一个是异步的观察者模式。
当两个对象之间松耦合,它们依然可以交互,但是不清楚彼此的细节,观察者提供了一种对象的设计,可以降低之间的耦合,避免对象的双向依赖。
举例:在Android中很多的Listener是观察者模式,比如点击事件的OnClickListener,就是为了避免对象的双向依赖。
package com.daming.java.observer;
public interface Observer {
void update(Observable observable, Object arg);
}
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 Observable object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {
return obs.size();
}
}
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);
}
}
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);
}
}
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");
}
}
observable2 :com.daming.java.observer.Observable@14318bbarg2 :14
observable :com.daming.java.observer.Observable@14318bbarg :14
observable2 :com.daming.java.observer.Observable@14318bbarg2 :I am daming
observable :com.daming.java.observer.Observable@14318bbarg :I am daming
Java源码中上述代码中用的是推模式,当然源码中也有拉模式,即主动查询的模式。拉模式就像广播一样,通过onReceive()方法拉起来一些动作的,还有像ContentObserver可以通过拉模式,当数据库发生改变的时候,通过onChange()方法来调用一些操作。
ContentObserver就是异步的观察者模式,异步的观察者有什么好处呢?不阻塞观察者的回调。在同步通知中会有阻塞问题,各个Observer的响应方法是串行的,如果有一个observer耗时的话就会阻塞其他observer接收者了,这样就有可能就会引起bug来,所以在设计的时候多考虑一些,是否考虑用异步的观察者模式,让并发处理快一些;我们通过一个简单的demo来学习下异步的观察者模式:
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();
}
}
}
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 mObservers = new ArrayList();
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();
}
}
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来发送异步的消息在主线程上来执行相应的操作。