Android 设计模式情景分析——观察者模式
观察者模式是一种使用频率非常高的模式,有时也被称作发布/订阅模式,属于行为型模式,它最常用的是 GUI 系统、订阅——发布系统,它一个重要作用就是解耦,使得它们之间的依赖性更小。观察者模式定义了对象间一种一对多的依赖关系,使得每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
1.观察者模式的使用情景
关联行为场景;事件多级触发场景;跨系统的消息交换场景(如消息队列、事件总线的处理机制)。
2.程序中使用观察者模式的优缺点
| - | 观察者模式 |
|---|---|
| 优点 | 观察者和被观察者之间是耦合抽象,应对业务变化;增强了系统灵活性、可扩展性。 |
| 缺点 | 开发调试变的比较复杂,Java中消息的通知是顺序执行,一个消息的卡顿会影响整体的执行效率,所以使用观察者模式还需要结合异步操作的方式。 |
3.观察者模式的UML类图
Subject:抽象主题,被观察(Observable)的角色;ConcreteSubject:具体主题;Observer:抽象观察者;ConcreteObserver:具体的观察者。
4.观察者模式的实现
观察者 Observer 和被观察者 Observable 是 JDK 中的内置类型。
1.创建观察者:
public class MyObserver implements Observer {
private String name;
public MyObserver(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + ", update:" + arg);
}
}
3.编写测试方法:
@Test
public void test() throws Exception {
// 被观察者
MyObservable observable = new MyObservable();
// 观察者
MyObserver observer1 = new MyObserver("test1");
MyObserver observer2 = new MyObserver("test2");
MyObserver observer3 = new MyObserver("test3");
MyObserver observer4 = new MyObserver("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
可以看到所有订阅了被观察者的观察者都接收到了更新消息,一对多的订阅——发布系统就完成了。
5.Android系统源代码中的应用情景
1.notifyDataSetChanged() 方法
我们在使用 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 (int i = 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 = new AdapterDataSetObserver();
// 将这个观察者注册到 Adapter 中,实际上是注册到 DataSetObservable 中
mAdapter.registerDataSetObserver(mDataSetObserver);
// 代码省略
} else {
// 代码省略
}
requestLayout();
}
// 代码省略
}
我们可以看到,在设置 Adapter 时会构建一个 AdapterDataSetObserver,也就是观察者,最后,将这个观察者注册到 Adapter 中。
到这里,我们就知道了,当 ListView 的数据发生变化时,调用 Adapter 的 notifyDataSetChanged() 方法,这个方法又调用 DataSetObservable 的 notifyChanged() 方法,这个方法又调用所有观察者(AdapterDataSetObserver)的 onChanged() 方法,在 onChanged() 方法中又会调用 ListView 重新布局的方法使得 ListView 刷新界面,这就是一个观察者模式。
Android 设计模式情景分析——观察者模式的更多相关文章
- 《Android系统源代码情景分析》连载回忆录:灵感之源
上个月,在花了一年半时间之后,写了55篇文章,分析完成了Chromium在Android上的实现,以及Android基于Chromium实现的WebView.学到了很多东西,不过也挺累的,平均不到两个 ...
- Android系统--Binder系统具体框架分析(二)Binder驱动情景分析
Android系统--Binder系统具体框架分析(二)Binder驱动情景分析 1. Binder驱动情景分析 1.1 进程间通信三要素 源 目的:handle表示"服务",即向 ...
- Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件
Android系统--输入系统(十三)Dispatcher线程情景分析_Reader线程传递事件 1. 输入按键 我们知道Android系统的按键分为三类:(1)Global Key;(2)Syste ...
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理 1. 回顾 我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理 ...
- Android : 跟我学Binder --- (4) 驱动情景分析
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- 10.7 android输入系统_Dispatcher线程情景分析_Reader线程传递事件和dispatch前处理
android输入系统C++最上层文件是com_android_serve_input_InputManagerService.cpp global key:按下按键,启动某个APP可以自己指定,修改 ...
- Android 设计模式 之 观察者模式
/* * 观察者模式 * 定义对象间的一种一个(Subject)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的 * 对象都得到通知并被自动更新 * * 当然, ...
- Android 设计模式之观察者模式(转载自:“http://blog.csdn.net/fangchongbory/article/details/7774044”)
/* * 观察者模式 * 定义对象间的一种一个(Subject)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的 * 对象都得到通知并被自动更新 * * 当然, ...
- Android设计模式系列
http://www.cnblogs.com/qianxudetianxia/category/312863.html Android设计模式系列(12)--SDK源码之生成器模式(建造者模式) 摘要 ...
随机推荐
- 算法(Algorithms)第4版 练习 1.5.22
package com.qiusongde; import edu.princeton.cs.algs4.StdOut; import edu.princeton.cs.algs4.StdStats; ...
- JS命令模式个人理解
JS命令模式个人理解 //BODY部分<body> <button id="execute">打开电视</button> <button ...
- jquery插件之jquery.extend和jquery.fn.extend的区别
jquery.extend jquery.extend(),是拓展jquery这个类,即可以看作是jquery这个类本身的静态方法,例如: <!DOCTYPE html> <html ...
- python函数的参数匹配
版本:一般用python2.7.6 python3.4.3会标注 1.不可变对象(整数.字符串)通过对象引用进行传递,在函数内部不可改变. >>> def f(a): ... a=1 ...
- GridView行中按钮的使用
转载自:http://blog.csdn.net/hongdi/article/details/6455947 GridView行中按钮的使用 在web项目的过程中,特别是开发ASP.NET应用程序, ...
- php 微信公众平台开发之微信群发信息
这篇文章主要为大家详细介绍了php微信公众平台开发之微信群发信息,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.目的 完成在微信公众号中群发消息.这里只是完成简单的文字发送.也可以发送语音图片 ...
- 使用myeclipes制造属于自己的jar
选定你需要在jar中包含的package或者class 步骤1:右键export导出, 步骤2:导出类型为java --JRE file. 步骤3:直接finish即可完成 如果希望你的jar带源码 ...
- JSP分页1
分页 1.什么分页? 第N页/共M页 首页 上一页 1 2 3 4 5 6 7 8 9 10 下一页 尾页 口 go 分页的优点:只查询一页,不用查询所有页! 2.分页数据 页面的数据都是由Servl ...
- zepto不支持animate({scrollTop:"100px"})的解决办法
在移动web项目的开发中,遇到一个通过点击页面自动到相应的楼层处的需求,最初的想法就是使用html的target属性进行切换,但实际效果十分死板,显得毫无交互性.该前端架构采用zepto这个轻库进行开 ...
- hihocoder-1284 机会渺茫(水题)
机会渺茫 时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi最近在追求一名学数学的女生小Z.小Z其实是想拒绝他的,但是找不到好的说辞,于是提出了这样的要求:对于给定的两 ...