基本需求:
- 气象站可以将每天测量到的温度,湿度,气压等等,以公告的形式发布出去(比如发布到自己的网站或第三方)
- 需要设计开放型API,便于其他第三方也能接入气象站获取数据
- 提供温度、气压和湿度的接口
- 测量数据更新时,要能实时的通知给第三方
传统方案:
通过对需求的分析,我们可以设计一个WeatherData类,其中包含getXxx()方法,可以让第三方接入,并得到相关信息
当有数据更新时,WeatherData调用dataChange()方法去更新数据,当第三方获取时,就能获取到最新的数据,当然也可以推送
WeatherData内部还需维护一个CurrentCondition对象,便于完成推送或通知
UML类图
代码实现
问题分析
- 其他第三方接入气象站获取数据问题
- 无法在运行时动态的添加第三方
- 违反了ocp原则,在WeatherData中,如果需要增加新的第三方应用,都需要创建一个对应的第三方的公告板对象,并加入到dataChange()方法中,不利于维护,也不是动态加入
基本介绍:
当对象间存在一对多关系时,则使用观察者模式(Observer),比如,当一个对象被修改时,则会自动通知依赖它的对象,观察者模式属于行为型模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知
基本原理
- 观察者模式类似订牛奶业务 例如:奶站/气象局:Subject 和 用户/第三方网站:Observer
- Subject:登记注册、移除和通知 一的一方(被观察者)
- registerObserver 注册
- removeObserver 移除
- notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送,看具体需求定
- Observer:接收输入 也就是第三方,可以有多个实现 多个一方(观察者)
- 对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化,比如这里的奶站是Subject,是1的一方。用户时Observer,是多的一方
UML类图(案例)
代码实现
jdk源码:
在jdk的Observer类和Observable类就使用到了观察者模式
Observer作为了观察者接口,提供了update()方法
Observable相当于Subject,作为被观察者,只不过在jdk源码中,Observable是一个类,而不是接口,提供了注册观察者,删除观察者,通知观察者的一系列管理观察者的方法
注意事项:
- 观察者和被观察者是抽象耦合的,建立一套触发机制
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
- 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
- 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化
- JAVA中已经有了对观察者模式的支持类
- 避免循环引用
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式