什么是观察者模式:让你的对象知悉现状
观察者模式是软件设计模式中的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常呼叫各个观察者所提供的方法来实现。
- 摘自维基百科
简单来说,观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态是,它的所有依赖者都会收到通知并自动更新。在观察者模式中,一对多依赖中的”一”一般被称作主题(Subject),而”多”则被称作观察者(Observer)。
观察者的类图
观察者模式的优点:松耦合
当2个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
观察者模式提供了一种对象设计,让主题和观察者之间松耦合。为什么呢?
- 关于观察者的一切,主题只知道观察者实现了某个接口(也就是Observer接口),主题不需要知道观察者具体是谁、做了些什么或其他任何细节;
- 任何时候我们都可以添加新的观察者。因为主题唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加观察者。事实上,在运行时我们可以用新的观察者取代现有的观察者,主题不会受到任何影响。同样的,也可以在任何时候删除某些观察者。
- 有新类型的观察者出现时,主题的代码不需要修改。假如我们有个新的具体类需要当观察者,我们不需要为了兼容新类型而修改主题的代码,所要做的就是在新的类里实现观察者接口,然后注册为观察者即可。主题不在乎别的,它只会发送通知给所有实现了观察者接口的对象。
我们可以独立地复用主题或者观察者。如果我们在其他地方需要使用主题或者观察者,可以轻易地复用,因为二者并非紧耦合。
改变主题或者观察者中的一方,并不会影响另一方。因为二者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由地改变他们。
观察者模式的使用
|
|
|
|
|
|
|
|
JDK内置的观察者模式
Java API有内置的观察者模式。java.util包内包含最基本的Observable类和Observer接口,这和我们的Subject接口和Observer接口很类似,Observable类和Observer接口使用上更方便,因为许多功能都已经事先准备好了。你甚至可以使用push或pull的方式传送数据。
java.util.Observable的不足
如同我们所见,Observable是一个”类”而不是一个”接口”,更糟糕的是,它甚至没有实现一个接口。不幸的是,java.util.Observable的实现有许多问题,限制了它的使用和复用。
我们从设计原则可以知道这不是好事。
首先,因为Observable是一个类,你必须设计一个类继承它。如果某类想同时具有Observable类和另一个父类的行为,就会陷入两难,毕竟Java不支持多继承。这就限制了Observable的复用能力(而复用能力不正是我们使用模式最原始的动机么?)。
再者,因为没有Observable接口,所以你无法建立自己的实现,和Java内置的Observer API搭配使用,也无法将java.util的实现换成另一套做法。
观察者模式在Spring中的应用-Spring事件驱动模型
事件机制的实现需要三部分,事件源、事件、事件监听器。下面我们分别来看。
事件:ApplicationEvent
|
|
ApplicationEvent继承自JDK的EventObject,Spring中所有的事件都需要继承自ApplicationEvent,并且通过source取得事件源。ApplicationEvent的实现类ApplicationContextEvent表示ApplicationContext的容器事件。
事件监听器:ApplicationListener
|
|
ApplicationListener继承自JDK的EventListener,所有的Spring监听器都要实现这个接口,这个接口只有一个onApplicationEvent()方法,该方法接受一个ApplicationEvent或其子类对象作为参数。在方法体中,可以通过不同对Event类的判断来进行相应的处理。当事件触发时,所有的监听器都会收到消息,如果你需要对监听器的接收顺序有要求,可以实现该接口的一个实现SmartApplicationListener,通过这个接口可以指定监听器接收事件的顺序。
事件源:ApplicationContext
ApplicationContext是Spring中的全局容器,翻译过来是”应用上下文”的意思,它用来负责读取bean的配置文档、管理bean的加载、维护bean之间的依赖关系,可以说是负责bean的整个生命周期,再通俗一点讲就是我们平时所说的IoC容器。
ApplicationContext作为一个事件源,需要显示地调用publishEvent()方法,传入一个ApplicationEvent对象作为参数,每当ApplicationContext发布ApplicationEvent时,所有的ApplicationListener就会被自动触发。
ApplicationEvent接口继承了ApplicationEventPublisher接口,后者有一个很重要的方法:
我们常用的ApplicatonContext都继承自 AbstractApplicationContext,像我们平时常见的ClassPathXmlApplicationContext、XmlWebApplicationContext也都是继承自它,AbstractApplicationContext是ApplicationContext接口的抽象实现类,在该类中实现了publishEvent()方法。
在这个方法中,我们看到一个getApplicationEventMulticaster(),这就要牵涉到另一个类 ApplicationEventMulticaster。
ApplicationEventMulticaster
ApplicationEventMulticaster 属于事件广播器,它的作用是把 ApplicationContext 发布的 Event 广播给所有的监听器。
在 AbstractApplicationContext 中有一个 applicationEventMulticaster 的成员变量,提供了监听器Listener的注册方法。
Spring事件模型总结
从上面可以看出,Spring的事件驱动模型使用的是 观察者模式。事件监听器 ApplicationListener 是观察者,ApplicationContext 是主题。