观察者模式,保证主题和若干观察者之间的一致性。
概述
有时又被称为发布-订阅Subscribe>模式、模型-视图View>模式、源-收听者Listener>模式或从属者模式
此种模式通常被用来实现事件处理系统
特定环境
- 一个对象改变,同时引发其他若干对象发生变化时
- 主动改变的对象和被动变化的对象之间相对独立,以便复用和维护
一类问题
一个系统,由一个对象和若干协作对象组成,同时要避免这些对象之间相互耦合
解决方案
- 抽象主题角色
- 具体主题角色
- 抽象观察者角色
- 具体观察者角色
抽象主题角色
一般由接口或抽象类实现
注册有若干抽象观察者的引用集
同时,能够增删抽象观察者,并在自身发生改变时,通知观察者作出相应变化
具体主题角色
一般由具体子类实现抽象主题角色,具有自己的状态
抽象观察者角色
一般由接口或抽象类实现
为所有具体观察者定义行为规范
并定义方法,接收通知并更新自身状态
具体观察者角色
一般由具体子类实现抽象观察者角色,具有自己的状态,随主题状态变化而变化
推模型和拉模型
在观察者模式中,又分为:
- 推模型
主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。- 拉模型
主题对象在通知观察者的时候,只传递少量信息
如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据
一般这种模型的实现中,会把主题对象自身通过 update 方法传递给观察者
这样在观察者需要获取数据的时候,就可以通过这个引用来获取了
两种实现方式的比较
推模型是假定主题对象知道观察者需要的数据;
而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值推模型可能会使得观察者对象难以复用,因为观察者的 update方法 是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update方法,或者是干脆重新实现观察者;
而拉模型就不会造成这样的情况,因为拉模型下,update 方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要
Java 中的 Observer 接口 和 Observable 类
Observer 接口 :观察者
Observable 类 : 主题,即被观察者
通过继承或实现它们,可以快速实现观察者模式,并且线程安全
另外,这两个类型使用的是 拉模型
参考
《JAVA与模式》之观察者模式,作者: java_my_life