Android源码中观察者模式的运用

2017-04-25 17:49单丹丹韩冬
电脑知识与技术 2017年2期
关键词:设计模式

单丹丹 韩冬

摘要:该文介绍了设计模式中观察者模式的基本概念,在理解观察者模式的基础上,对Android源码中观察者模式的运用进行了深入的分析,说明了观察者模式在程序设计中的重要性。

关键词:设计模式;观察者模式;Android源码

中图分类号:TP311 文献标识码:A文章编号:1009-3044(2017)02-0068-02

1觀察者模式介绍

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

2观察者模式使用场景

1)当一个抽象模型有两个方面, 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

2)当对一个对象的改变需要同时改变其他对象, 而不知道具体有多少对象需要被改变。

3)当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之, 不希望这些对象是紧密耦合的。

3观察者模式中的角色及UML类图表示

1)抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

2)具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

3)抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

4)具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

用UML类图表示如下:

4 观察者模式的Android源码实现

Adapter是ListView中最重要的一个点。向ListView中添加数据后,都会调用notifyDataSetChanged()方法。notifyDataSetChanged方法定义在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 {

public void notifyChanged() {

synchronized(mObservers) {

// 遍历调用所有观察者的onChanged方式

for (int i = mObservers.size() - 1; i >= 0; i--) {

mObservers.get(i).onChanged();}}}

// 代码省略

}

上段代码中的观察者由ListView通过setAdapter方法来设置Adapter时构建的AdapterDataSetObserver创建,代码如下:

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();

// 创建一个一个数据集观察者

mDataSetObserver = new AdapterDataSetObserver();

// 将这个观察者注册到Adapter中,实际上是注册到DataSetObservable中

mAdapter.registerDataSetObserver(mDataSetObserver);

// 代碼省略

} else {// 代码省略 }

requestLayout();}

通过以上的代码,被观察者、观察者都已经被创建。

下面具体说明AdapterDataSetObserver是如何运作。AdapterDataSetObserver定义在ListView的父类AbsListView中,代码如下 :

class AdapterDataSetObserver extends AdapterView.AdapterDataSetObserver {

public void onChanged() {

super.onChanged();

if (mFastScroller != null) {

mFastScroller.onSectionsChanged();}}

//代码省略

}

同时AdapterDataSetObserver又继承自AbsListView的父类AdapterView的AdapterDataSetObserver。当ListView的数据发生变化时,会调用Adapter的notifyDataSetChanged函数,这个函数中会调用DataSetObservable的notifyChanged函数,notifyChanged函数又会调用所有观察者的onChanged方法。这就是一个观察者模式!

最后我们对观察者模式的源码实现进行一个梳理:AdapterView中有一个内部类AdapterDataSetObserver,在ListView设置Adapter时会构建一个AdapterDataSetObserver,并且注册到Adapter中,这就是一个观察者。而Adapter中包含一个可观察者数据集DataSetObservable,在数据数量发生变更时,开发者手动调用AdapternotifyDataSetChanged,而notifyDataSetChanged实际上会调用DataSetObservable的notifyChanged函数,该函数又会遍历所有观察者的onChanged函数。在AdapterDataSetObserver的onChanged函数中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,从而对用户界面进行更新。

上述代码可以运用于杂志订阅的事例中,杂志是主题,观察者是订阅者,当出版新杂志时候,这个事件会自动通知所有的订阅者。除此以外也可以运用于气象站,为气象站提供用户订阅气象信息的服务。总是,观察者模式在日常生活中的运用十分广泛。

5观察者模式总结

观察者模式的主要的作用就是对对象解耦,将观察者和被观察者完全隔离。

1)观察者模式的优点

观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。

2)观察者模式的缺点

在应用观察者模式时需要考虑一下开发小路问题,程序中包括一个被观察者和多个被观察者额,开发和调试比较复杂,而且Java中的消息的通知默认是顺序执行的,一个观察者的卡顿会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。

3)观察者模式的重要性

观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,它可以将消息一一通知给所有的观察者。观察者模式基于接口而不是具体的实现的特点,为程序设计提供了更大的灵活性,在程序设计中有着重要的地位。

参考文献:

[1] 何红辉,关爱民.Android源码设计模式解析与实战[M].北京:人民邮电出版社, 2015:224-245.

[2] 何宏辉.Android开发进阶从小工到专家[M].北京:人民邮电出版社, 2016:195-215.

[3] 郭霖.第一行代码[M].北京:人民邮电出版社, 2014:127-135.

[4] 李刚.疯狂安卓讲义[M].北京:电子工业出版社, 2015:88-97.

猜你喜欢
设计模式
设计模式识别的特征信息分类研究
“1+1”作业设计模式的实践探索
基于能力目标培养的药学专业课程整体教学设计模式研究
引入线索约束的设计模式变体挖掘研究*
设计模式挖掘的有效性评估策略
智慧图书馆环境下的融贯式服务设计模式研究
三维协同设计模式下的航天项目管理实践与展望
交通机电工程设计模式创新探讨
应用型高校学生程序设计能力培养研究
基于“双师制”指导下的工业设计专业毕业设计模式