模式定义
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
模式示例
Java本身对观察者模式的实现有良好的支持,被观察者类只要继承java.util.Observable
即可,观察者类只要实现java.util.Observer
接口即可。下面写一个Demo来描述观察者模式,这个示例如下,一个新闻事件中心,可以能会发生各种事件,有几家报社在新闻事件中心发生事件后,会根据事件做相应的报道,这是典型的一对多关系。
- 定义被观察者接口,新闻中心实现被观察者接口,支持事件通知、添加或移除报社(观察者)操作;
- 定义观察者接口,报社要实现该接口,当事件发生时,可以对事件进行响应。
- 定义客户端来演示
定义被观察者
1 | /** |
定义观察者接口
1 | /** |
定义真正被观察者NewsData,实现Subject接口
1 | /** |
定义四家报社(真正的观察者)这四家报社对新闻的关注点不同,可以选择性的报道:
1 | /** |
1 | /** |
1 | /** |
1 | /** |
定义客户端,进行新闻播报
1 | public class NewsStation { |
输出结果
1 | Ccc headlineNews: 'Big objects found' in AirAsia hunt |
模式总结
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。观察者和被观察者是抽象耦合的,被观察者持有一个观察者列表,在自身发生变化时,遍历该列表逐一通知。
观察者模式主要解决,一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
优缺点
- 优点
- 观察者和被观察者是抽象耦合的。
- 建立一套触发机制。
- 缺点
- 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间;
- 可能产生循环依赖的问题,如观察者和被观察者间可能存在循环依赖的问题(EventBus使用时就会产生这种问题)
- 观察者模式只能告诉观察者被观察者发生了变化,但不能说明具体发生了什么变化。
使用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
注意事项
- JAVA 中已经有了对观察者模式的支持类。
- 避免循环引用。
- 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。