观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。观察者模式降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系;在目标与观察者之间建立了一套触发机制。
模式结构
观察者模式的主要角色:
- 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
- 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
- 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
源码分析
一说到观察者模式我们就想到监听器,那么在这个设计模式里面我们就学习并分析一下spring的事件监听机制,熟悉观察者模式的同时学习监听器原理。
首先我们先学习如何在spring中发布一个事件和注册对应的事件监听器:
代码语言:javascript复制// 自定义的事件
public class MyApplicationContextEvent extends ApplicationEvent {
public MyApplicationContextEvent(Object source) {
super(source);
}
}
// 自定义的事件监听器
@Component
public class MyListener implements ApplicationListener<MyApplicationContextEvent> {
@Override
public void onApplicationEvent(MyApplicationContextEvent myApplicationContextEvent) {
System.out.println("myApplicationContextEvent");
}
}
// 测试类
@Component
public class Test{
@Autowired
private ApplicationContext applicationContext;
public void message(){
applicationContext.publishEvent(new MyApplicationContextEvent())
}
}
上面的代码中 MyApplicationContextEvent
是我们定义的一个事件,MyListener
是我们定义的事件对应的监听器,并注册到了spring容器中。当我们调用 publishEvent
发布一个事件的时候我们的监听器就会监听到事件的发布,执行onApplicationEvent
方法。
下面我们分析一下spring监听器的原理。spring监听器执行过程是这样的:当调用publishEvent
方法的时候,它会执行如下代码:
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
从容器中拿出 SimpleApplicationEventMulticaster
的bean 并执行它的multicastEvent
方法来通知对应的监听器来执行监听方法,这个bean也叫做派发器
。multicastEvent
源码如下:
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
在这里,SimpleApplicationEventMulticaster(派发器)
是主题角色
,监听器是观察者
,发布事件是触发观察者的条件。
其实,大名鼎鼎的 Reactive Programming
(响应式编程) 也是从观察者模式脱胎而出的。我们所用的 webflux
和 netty
就是基于 rstream
来设计的。响应式编程和传统的阻塞式编程编程模型上有很大的差别,感兴趣的小伙伴可以去看看。