参与者
目标Subject
目标知道它的观察者,可以有任意多个观察者
提供注册和删除观察者的接口, 以及一个通知接口notify
观察者Observer
提供一个目标发出通知时更新自身的接口update
ConcreteSubject
具体目标存储了各自的状态,并在状态发生改变时通知与其关联的观察者
ConcreteObserver
维护了它关联的Subject的引用,和相应的状态,并提供一个更新方法以保持自身状态与目标状态一致<br>
优缺点<br>
支持广播通信,目标发送通知不需要指定它的接收者,通知被自动广播给已向该目标注册的所有观察者,可以在任意时刻增加和删除观察者,处理一个通知取决于观察者<br>
缺点:因为一个观察者不知道其他观察者的存在,它对目标的更新可能会引起一系列对观察者以及相关联对象的更新,如果依赖准则处理不当可能会引起错误的更新<br>
实现
如果目标很多,观察者很少,为了避免每个目标都维护对应观察者的引用造成空间浪费,可以用hash表维护目标到观察者的映射,这样没有观察者的目标就不占用任何存储空间<br>
观察者可以观察多个目标,这样的话update方法的参数就要加目标参数,以便知道是哪个目标状态更新了。或者提供一个获取状态更新的目标集合的方法,比如NIO selector
调用notify的时机: 1、目标每次状态更新都触发一次notify通知,这样客户端使用简单,但是容易导致频繁通知。2、由客户端调用notify,这样不会导致不必要的通知,但增加了使用难度,可能会遗漏触发通知
通知的时候要注意,必须在目标状态一致时通知
通知的方式有推模式和拉模式<br>
推模型
目标向观察者发送更新的状态信息,通常是在update参数中定义
需要目标假定观察者需要哪些信息,这使得观察者可能难以复用<br>
拉模型
目标只告诉观察者状态更新了,具体更新信息需要观察者再向目标查询获得
强调的是目标不知道它的观察者,观察者更易于扩展,但效率较差,因为观察者需要在没有目标帮助的情况下获取什么状态改变了<br>
为了提高更新的效率,可以在注册观察者时指定它感兴趣的事件,notify方法参数增加事件参数,特定事件触发时,只通知对事件感兴趣的观察者<br>