zl程序教程

您现在的位置是:首页 >  Java

当前栏目

设计模式-观察者模式

2023-02-18 16:39:43 时间

观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。观察者模式降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系;在目标与观察者之间建立了一套触发机制。

模式结构

观察者模式的主要角色:

  • 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  • 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  • 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  • 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

源码分析

一说到观察者模式我们就想到监听器,那么在这个设计模式里面我们就学习并分析一下spring的事件监听机制,熟悉观察者模式的同时学习监听器原理。

首先我们先学习如何在spring中发布一个事件和注册对应的事件监听器:

// 自定义的事件
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 (响应式编程) 也是从观察者模式脱胎而出的。我们所用的 webfluxnetty 就是基于 rstream 来设计的。响应式编程和传统的阻塞式编程编程模型上有很大的差别,感兴趣的小伙伴可以去看看。