介绍
观察者模式是一个使用率非常高的模式,它最常用的地方是 GUI 系统,订阅 - 发布系统。因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得他们之间的依赖性更小,甚至做到毫无依赖。以 GUI 系统来说,应用的 UI 具有易变性,尤其是前期随着业务的改变或者产品的需求修改,应用界面会经常性修改,但是业务逻辑基本变化不大,此时,GUI 系统需要一套机制来应对这种情况,使得 UI 层与具体的业务逻辑解耦,可以使用观察者模式。
定义
定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
Subject 抽象主题,也就是被观察 (Observable) 的角色,把所有观察者的引用保存到一个集合里,并提供一个接口,可以增加和删除集合中的观察者对象
ConcreteSubject 具体主题,也就是具体被观察者,具体主题内部状态发送改变时,给所有注册过的观察者发出通知
Observer 观察者,是观察者的抽象类,定义了一个接口,使得在得到主题的更改通知时更新自己
ConcreteObserver 具体观察者,该角色实现了抽象观察者所定义的更新接口
Observer 和 Observable 是 JDK 中的内置类型。
Observer 接口中定义了 update 抽象方法,当 Observable 中有变化时会调用 notifyObservers 方法通知所有的观察者更新。
Android 源码中的观察者模式
Adapter 中的观察者模式
BaseAdapter 是一个观察者模式!!!
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public boolean hasStableIds() {
return false;
}
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
AdapterView 中有一个内部类 AdapterDataSetObserver,在 ListView 中设置 Adapter 时会构建其一个内部类 AdapterDataSetObserver 的对象,该类继承自 AdapterView 的 AdapterDataSetObserver,也就是一个观察者。
接着将 AdapterDataSetObserver 对象注册到 Adapter 中,Adapter 类中有一个数据集可观察者 DataSetObservable 对象,在注册时,将 AdapterDataSetObserver 放入到 DataSetObservable 内部的一个 List 集合 mObservers 中
当数据数量发生变更时,开发者手动调用 Adapter 的 notifyDataSetChanged 方法时,会调用 DataSetObserver 的 notifyChanged 方法,notityChanged 方法中则会遍历其内部的 mObservers 集合中的所有 AdapterDataSetObserver 对象,并调用其 onChanged 方法
AdapterDataSetObserver 也就是观察者对象,在 AdapterView 的内部类 AdapterDataSetObserver 的 onChanged 方法中会调用 requestLayout 方法重新进行布局,更新用户界面
AdapterView 中的 AdapterDataSetObserver 为观察者,Adapter 中的 DataSetObservable 为被观察者,当注册时将与 AdapterView 中的 AdapterDataSetObserver 对象注册到 Adapter 的 DataSetObservable 中。在数据发生变化是,通过 DataSetObservable 来通知 AdapterDataSetObserver 最后通知到 AdapterView 重新布局,完成界面刷新
BroadcastReceiver 中的观察者模式
BroadcastReceiver 是 Android 四大组件之一,它作为应用内、进程间的一种重要通信手段,能够将某个消息通过广播的形式传递给对应的广播接收器对象。接收对象需要通过 Context 的 registerReceiver 方法注册到 AMS 中,当通过 sendBroadcast 发送广播时,所以注册了对应 IntentFilter 的 BroadcastReceiver 对象就会接收到这个消息,BroadcastReceiver 的 onReceive 方法就会被调用,这就是一个典型的 发布--订阅 模式,也就是我们的观察者模式。
优点
观察者和被观察者之间抽象耦合,应对业务变化
增强系统灵活性、可扩展性
缺点
开发效率和运行效率,当一个被观察者被多个观察者订阅时调试比较复杂
Java 中消息通知默认是顺序的,一个观察者卡顿,会影响整体执行效率,这种情况下,采用异步方式