定义
观察者模式也叫订阅发布者模式。订阅者们订阅某主题,当主题数据或者状态发生变化时,通知订阅了本主题的订阅者们进行更新。
组成及类图
- 抽象主题Subject
(1) 抽象主题可以是一个抽象类或者一个接口。
(2)拥有一个新数对象或者一个状态属性。
(3)拥有一个观察者集合,存放订阅了本主题的观察者们。可在实例化主题时,实例化这个集合属性。
(4)支持通知观察者们。当数据更新或者状态发生变化时,推送新数据给订阅了本主题的观察者们,通知他们进行自动更新。
(5)支持添加某个观察者。
(6)支持移除某个观察者。 - 具体主题
(1)实现抽象主题的各个抽象方法。
(2)主题不用关心数据是何时变化的,如何变化的。当数据变化时,通过set方法将新数据传给主题,在set方法里通知观察者们。 - 抽象观察者Observer
(1)抽象观察者可以是一个接口或者一个抽象类。
(2)拥有一个订阅的主题。
(3)支持订阅主题成为观察者。
(4)支持取消订阅,数据更新时不要再通知我了,i dont care!!
(5)支持更新数据,然后干点啥。 具体观察者
(1)拥有一个抽象主题的引用。提供set方法支持主题的更改,并在set方法里进行订阅注册。
(2)实现观察者抽象方法。类图
稍后上传。。。
场景举例
某化妆品品牌的VIP会员注册功能。只有注册为VIP会员,才会收到本店的打折消息和优惠。当然,你是土豪的话,也可以随时退订。
模式总结
(1)观察者模式很好的降低了主题和观察者之间的耦合度。主题不用关心自己具体有哪些订阅者,订阅者可以随时订阅或者取消订阅主题,而不用更改主题代码。
(2)数据同步有两种方式,一种是观察者订阅主题,通过主题的get方法,从主题那里拿;另一种是观察者订阅主题,在主题通知观察者更新时,推送数据给观察者们。个人比较支持第二种,觉得主题不应该提供数据的get方法。因为提供get方法的话,观察者只要拥有主题的引用,不用订阅,不就可以拿到新数据了吗!?要知道,主题才是数据的拥有者,数据的分配权归主题所有,不是谁想拿就能拿的。
(3)主题拥有数据,主题怎么获得外界的新数据呢,大多数人肯定想通过set方法呗,可是这样的话,订阅者可能会通过主题引用更改数据。要注意set方法的访问权限。
(4)留下几个疑问:
为啥把主题抽象成接口或抽象类?
提高一个模块(接口、抽象类)的复用潜力,使我们设计的目标!
观察者模式就是一对多的依赖,不能是多对多的依赖吗?比如一个观察者订阅多个主题?
如果主体的数据来自外界其他模块,它就不得不通过set方法获得新数据,此时观察者们很可能通过这个set方法更改数据的!咋整呢??