观察者模式(Observer Pattern)

2024-05-17 09:52

1. 观察者模式(Observer Pattern)

观察者模式又称为发布订阅模式。一个发布者对应多个订阅者,一旦发布者的状态发生改变时,订阅者将收到订阅事件。
  
 先看看一个生活中的例子:
   我们使用想浏览Java相关的文章,于是我们点击订阅了[Java专题],当[Java专题]有新文章发布就会推送给我们,当然其他人也可以订阅[Java专题]并收到[Java专题]的推送。这就是观察者。 定义对象间的一对多关系,当一个对象的状态发生变化时,所依赖于它的对象都得到通知并主动更新。在观察者模式中,多个订阅者成为观察者(Observer),被观察的对象成为目标(Subject)。
  
 实现观察者模式的方法不只一种,但是以包含Subject与Observer接口的类设计的做法最常见。(Java API 内置观察者模式用的是Observer接口与Observable类)
  
 观察者模式UML图:
                                          
 先定义观察者模式的接口
  
 在观察者模式的实现上,有推模式和拉模式两种方式。
  
 上面例子中
   void updateByPush(Object obj) 就是推模式;
   void updateByPull(Subject subject)就是拉模式
  
 java.util包内包含最基本的Observer接口与Observable类(其实对应的就是Subject类)
   我们看一下Observer源码
  
 我们看到update更新方法有两个参数:Observable、Object,可见Java API 内置观察者模式同时支持[拉]和[取]
  
 我们再来看看Observable类源码
  
 注意Observable是一个类,而不是接口,这有一定的局限性。因为如果某个类想同时具有Observable类和另一个超类的行为,就会陷入两难,毕竟Java不支持多重继承。
  
 有点需要特别提一下的就是,Java API 内置的Observable需要调用一下 setChanged();观察者才能收到推送,我们看一下源码,发现notifyObservers方法里有判断changed的状态为true才去通知观察者。
  
 我们自己实现观察者模式的时候是没有这一点的,那加上这一个标志位有什么好处?好处就是更灵活,Observable类只提供这个boolean值来表明是否发生变化,而不定义什么叫变化,因为每个业务中对变化的具体定义不一样,因此子类自己来判断是否变化;该变量既提供了一种抽象(变与不变),同时提供了一种观察者更新状态的可延迟加载,通过后面的notifyObservers方法分析可知观察者是否会调用update方法,依赖于changed变量,因此即使被观察者在逻辑上发生改变了,只要不调用setChanged,update是不会被调用的。如果我们在某些业务场景不需要频繁触发update,则可以适时调用setChanged方法来延迟刷新。
  
  阿里云折扣快速入口

观察者模式(Observer Pattern)