观察者模式是一种使用频率非常高的模式,有时也被称作发布 / 订阅模式,属于行为型模式,它最常用的是 GUI 系统、订阅——发布系统,它一个重要作用就是解耦,使得它们之间的依赖性更小。观察者模式定义了对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
关联行为场景;事件多级触发场景;跨系统的消息交换场景(如消息队列、事件总线的处理机制)。
- | 观察者模式 |
---|---|
优点 | 观察者和被观察者之间是耦合抽象,应对业务变化;增强了系统灵活性、可扩展性。 |
缺点 | 开发调试变的比较复杂,Java 中消息的通知是顺序执行,一个消息的卡顿会影响整体的执行效率,所以使用观察者模式还需要结合异步操作的方式。 |
Subject:抽象主题,被观察(Observable)的角色;ConcreteSubject:具体主题;Observer:抽象观察者;ConcreteObserver:具体的观察者。
观察者 Observer 和被观察者 Observable 是 JDK 中的内置类型。
1. 创建观察者:
- public class MyObserver implements Observer{
- privateString name;public MyObserver(String name) {this.name = name;
- }@Override
- public void update(Observable o, Object arg) {
- System.out.println(name +", update:"+ arg);
- }
- }
2. 创建被观察者:
- public class MyObservable extends Observable{
- public void postNewPublication(String content) {// 标识状态或者内容发生改变setChanged();// 通知所有观察者notifyObservers(content);
- }
- }
3. 编写测试方法:
- @Test
- public void test()throwsException {// 被观察者MyObservable observable =newMyObservable();// 观察者MyObserver observer1 =newMyObserver("test1");
- MyObserver observer2 =newMyObserver("test2");
- MyObserver observer3 =newMyObserver("test3");
- MyObserver observer4 =newMyObserver("test4");// 将观察者注册到被观察者对象的观察者列表中observable.addObserver(observer1);
- observable.addObserver(observer2);
- observable.addObserver(observer3);
- observable.addObserver(observer4);// 发布消息observable.postNewPublication("new");
- }
输出结果:
- test4, update:new
- test3, update:new
- test2, update:new
- test1, update:new
可以看到所有订阅了被观察者的观察者都接收到了更新消息,一对多的订阅——发布系统就完成了。
我们在使用 ListView 添加数据后,都会调用 Adapter 的 notifyDataSetChanged() 方法来动态更新数据。
notifyDataSetChanged() 方法被定义在 BaseAdapter 中,BaseAdapter 就是一个观察者模式:
- public abstract class BaseAdapter implements ListAdapter,
- SpinnerAdapter {
- // 数据集观察者
- private final DataSetObservable mDataSetObservable = new DataSetObservable();
- public void registerDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.registerObserver(observer);
- }
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.unregisterObserver(observer);
- }
- // 当数据集变化时,通知所有观察者
- public void notifyDataSetChanged() {
- mDataSetObservable.notifyChanged();
- }
- // 代码省略
- }
我们跟进查看 mDataSetObservable.notifyChanged() 方法:
- public class DataSetObservable extends Observable<DataSetObserver> {
- // 调用每个观察者的 onChanged() 方法来通知它们被观察者发生了变化
- public void notifyChanged() {synchronized(mObservers) {// 调用所有观察者的 onChanged() 方法
- for(inti = mObservers.size() -1; i >=0; i--) {
- mObservers.get(i).onChanged();
- }
- }
- }// 代码省略}
这段代码就是在 mDataSetObservable.notifyChanged() 中遍历所有观察者,并且调用它们的 onChanged() 方法,从而告知观察者发生了变化。
那么这些观察者是哪里来的呢?其实是 ListView 通过 setAdapter() 方法设置 Adapter 产生的,我们来看看相关代码:
- public class ListView extends AbsListView{
- // 代码省略
- @Override
- public void setAdapter(ListAdapter adapter) {// 如果已经有了一个 Adapter,那么先注销该 Adapter 对应的观察者
- if(mAdapter !=null&& mDataSetObserver !=null) {
- mAdapter.unregisterDataSetObserver(mDataSetObserver);
- }// 代码省略
- super.setAdapter(adapter);if(mAdapter !=null) {
- mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
- mOldItemCount = mItemCount;// 获取数据的数量mItemCount = mAdapter.getCount();
- checkFocus();// 这里注意:创建一个一个数据集观察者mDataSetObserver =newAdapterDataSetObserver();// 将这个观察者注册到 Adapter 中,实际上是注册到 DataSetObservable 中mAdapter.registerDataSetObserver(mDataSetObserver);// 代码省略}else{// 代码省略}
- requestLayout();
- }// 代码省略}
我们可以看到,在设置 Adapter 时会构建一个 AdapterDataSetObserver,也就是观察者,最后,将这个观察者注册到 Adapter 中。
到这里,我们就知道了,当 ListView 的数据发生变化时,调用 Adapter 的 notifyDataSetChanged() 方法,这个方法又调用 DataSetObservable 的 notifyChanged() 方法,这个方法又调用所有观察者(AdapterDataSetObserver)的 onChanged() 方法,在 onChanged() 方法中又会调用 ListView 重新布局的方法使得 ListView 刷新界面,这就是一个观察者模式。
来源: http://blog.csdn.net/smartbetter/article/details/70755775