类图
- subject主题类接口提供注册,取消注册,以及通知观察者三个标准方法
- 观察者提供统一update方法,并持有sucject主题类的引用(方便随时注册或取消注册)
- 主题类接口会提供一个集合类,一般示例中都是普通list来存储注册的观察者引用,在实际开发中应该使用线程安全的集合类,如vector等。
- 经典的实现方式都是主动推送数据模式,但是由于不是subject中所有的数据都是所有观察者所关心的,所以有第二种“拉”模式,subject数据更新时只需要通知所有观察者数据更新了,具体更新了什么需要观察者接到通知后去主动同多subject类提供的getter方法拉取自己所需的数据,按需索取。所以,subject里也会有一些getter方法。
模式优点
- 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
- 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
- 观察者模式满足“开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。
jdk中java.util包中提供的观察者模式实现工具
observable,相当于subject主题类,他的最大的不同在于,多了一个setChange方法,该方法为protected,用处在于,之前介绍的观察者模式太过于敏感,只要数据有一点点更新就会通知全部的观察者,有了setchange方法,就可以实现自己的通知逻辑,如某个属性改变范围超过了100才通知等等。另外,他的观察者引集合是通过vector实现的。
observer,观察者,和前面的观察者一模一样
observable的缺点:
1.它是一个类,会受到java的单继承限制。也没有observable接口,所以也不能建立自己的实现来搭配jdk的api使用
2.他的关键方法setchanged被保护起来了,如果要自己基于observable实现一个主题类,就必须以继承的方式来实现,不能将它以组合的方式放进自己的主题实现类中
观察者模式通知方式默认都为同步,是否可以改为异步执行?
- 手动实现异步,将notifyObserver方法改写成以executor提交到异步线程池的方式。
- 使用spring的事件监听器实现,可指定同步还是异步通知,异步的话可设置线程池大小等。(spring4.1后好像对于事件这块使用更加便捷了)
实现以topic为维度的观察模式?
- 把vector替换为concurrenthashmap,以topic为key,观察者引用list为value来存储
观察者模式实际应用
- 在企业项目中已经被用烂了的消息中间件机制,发布订阅模式。
- socket服务端接收到客户端消息后发布消息到来消息,不同的业务逻辑来订阅并处理消息。
最后。观察者在接收被推送数据时,不应该对推送顺序敏感!!