这篇博客主要总结一下观察者模式。
观察者模式应该算是众多设计模式中, 应用比较广,同时也比较好理解的模式了。
因此这里直接给出它的定义: 观察者模式定义了对象之间的一对多依赖, 这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式的思想基本上可以用上图来说明。
有状态的对象将作为消息发布者, 负责将状态变化的信息通知给观察者们。
如图所示: 加入了订阅组的用户就是消息发布者的观察者, 它们会在必要时收到通知消息。
没有加入订阅组的用户4,不会收到通知信息。
用户可以自由的加入和离开订阅组。
这个过程,就像你在新闻APP中订阅某个专题一样。 如果你订阅了该专题, 那么有该专题的新闻出现时,就会主动推送给你。 如果某天你对该专题没兴趣了, 就可以取消订阅,此时就不会收到任何推送新闻了。
接下来,我们看看观察者模式相关的类图:
如上图所示,主题只需要知道观察者实现了Observer接口,而不需要知道其它的细节。 因此实际的主题对象,例如图中的ConcreteSubject对象,只需要将观察者当作Observer保存。
同理,观察者也不需要知道主题的实现细节,只需要知道主题实现了Subject接口。 通过Subject中的registerObserver接口,观察者可以将自己注册到主题; 通过removeObserver接口,观察者可以取消对主题的关注。
当主题发现状态改变时,就可以调用notifyObserver方法,调用保存的所有观察者的update函数。
此外,主题对象还可以提供getState和setState方法,供其它对象主动获取或设置主题的状态。
通过上图可以看出,整个观察者模式提供了一种松耦合的设计。 主题和观察者之间可以交互,但不需要清楚彼此的细节。 只要遵循它们之间定义的接口,那么改变主题或观察者其中一方,并不会影响另一方。
最后,我们来看看Android源码中使用观察者模式的例子。
Android中使用观察者模式的地方很多,此处我们以RIL的通知框架为例。
如图所示,RIL接收modem上报的信息,作为整个通知框架的消息发布者,即主题。 RIL继承BaseCommands类,后者实现了CommandsInterface接口。
CommandsInterface接口中定义了许多注册、反注册函数,这里以RadioState相关的函数为例。 ServiceStateTracker作为观察者,需要将自己的Handler等参数注册到主题中。
主题将利用利用这些参数构造出Registrant对象, 并保存到BaseCommands中的mRadioStateChangedRegistrants中。
当RadioState发生变化时,BaseCommands就会通知mRadioStateChangedRegistrants中的所有Registrant。 Registrant就会利用自身的Handler发送消息给实际的观察者ServiceStateTracker。
RIL通知框架的类图与上文提到的观察者模式类图基本一致, 唯一的区别是观察者并没有继承接口对象,而是将Handler注册到主题中。 考虑到Handler在Android中的普及程度,实质上这也可以看作一种针对“接口”的编程。
