观察者设计模式
观察者模式又叫发布-订阅(Publish/Subscribe)模式。
观察者模式 定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
使用场景
观察者模式原理
- 观察者模式类似订牛奶业务
- 奶站/气象局:Subject
- 用户/第三方网站:Observer
Subject:登记注册、移除和通知 - registerObserver 注册
- removeObserver 移除
- notifyObservers() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送, 看具体需求定
Observer:接收输入
观察者模式: 对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject 通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方。用户是 Observer,是多的一方。
观察者模式的好处
- 观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知。
- 这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码, 遵守了 ocp 原则。
- 观察者的动机:将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而导致各个类之间紧密耦合,这样会给维护、扩展和重用都带来不便。所以就诞生了观察者模式。
- 什么时候用观察者模式? 当一个对象的改变需要同时改变其他对象的时候,并且它不知道具体有多少对象待改变时,就应该考虑使用观察者模式了。还有就是,当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,这时用观察者模式就可以将这两者封装在独立的对象中使用它们各自独立地改变和复用。
- 总的来讲,就是观察者模式所做的工作就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。(依赖倒转原则)
在Spring中的应用
实现方式
spring的事件驱动模型使用的是观察者模式,Spring中的Observer模式常用的地方是listener的实现。
具体实现
事件机制的实现需要三个部分,事件源、事件、事件监听器。
ApplicationEvent抽象类 ==事件
继承自jdk的EventObject,所有的事件都需要继承ApplicationEvent,并且通过构造器参数source得到事件源。
该类的实现类ApplicationContextEvent表示ApplicationContext的容器事件。
代码:
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationListener接⼝ ==事件监听器
继承自jdk的EventListener,所有的监听器都要实现这个接口。
这个接口只有一个onApplicationEvent()方法,该方法接收一个ApplicationEvent或其子类对象作为参数,在方法体中,可以通过不同的Event类来判断然后进行相对应的处理。
代码:
public interface ApplicationListener <E extends ApplicationEvent > extends EventListener {
void onApplicationEvent (E event); }
ApplicationContext接⼝ ==事件源
ApplicationContext是spring中的全局容器,翻译过来是”应⽤上下⽂”。
实现了ApplicationEventPublisher接⼝。
职责:
负责读取bean的配置⽂档,管理bean的加载,维护bean之间的依赖关系,可以说是负责bean的整个⽣命周期,再通俗⼀点就是我们平时所说的IOC容器。
代码:
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
}
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
} getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
ApplicationEventMulticaster抽象类 ==事件源中publishEvent⽅法需要调⽤其⽅法getApplicationEventMulticaster
属于事件⼴播器,它的作⽤是把Applicationcontext发布的Event⼴播给所有的监听器。
代码:
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {
private ApplicationEventMulticaster applicationEventMulticaster;
protected void registerListeners() {
// 首先注册静态指定的监听器
for f(ApplicationListener < ? > listener :getApplicationListeners()){
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 不要在此处初始化 FactoryBeans:我们需要保留所有常规 bean
// 未初始化以让后处理器应用于它们
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}
}