原理
观察者模式属于行为模式,行为模式主要解决类和对象之间交互问题。
含义:在对象之间定义一个一对多的依赖,当一个对象状态改变时,所有依赖的对象会自动通知。
被依赖的对象被观察者(Observable) ,依赖的对象观察者(Observer),当然也可以叫发布-订阅等。
一个case
比如我们维护的用户中心,当用户进行注册的时候,就进行通知发送短信、WA、邮件等。
1.第一步,先定义被观察者接口,主要就是注册、删除、已经通知观察者。
/**
* @author qxlx
* @date 2024/4/13 22:25
*/
public interface Subject {
/**
* 注册
* @param observer
*/
void registerObserver(Observer observer);
/**
* 删除
* @param observer
*/
void deleteObserver(Observer observer);
/**
* 发送事件
* @param message
*/
void notifyObservers(String message);
}
2.定义贯彻者具体的行为
public interface Observer {
void notify(String message);
}
3.被观察者的具体实现,可以发送通过接口注册或删除观察者,当被观察者执行用户注册的方法时,就会触发通知观察者进行处理。
这里需要明确下,可以采用同步的方式 或者异步方式。因为对于注册接口来说响应时间还是比较重要的,采用线程的方式 可以提高接口性能。
/**
* @author qxlx
* @date 2024/4/13 22:27
*/
public class ConcreteSubject implements Subject {
private List<Observer> observerList = new CopyOnWriteArrayList<>();
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void deleteObserver(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObservers(String message) {
// 1.同步调用
// 2.异步非阻塞
observerList.forEach(o -> o.notify(message));
// new Thread()
new Thread(() -> {
observerList.forEach(o -> o.notify(message));
}).start();
// 线程池
ThreadPoolUtil.getThreadPool(10).
execute(() -> observerList.forEach(o -> o.notify(message)));
}
}
4.定义具体的观察者实现类,发送邮件 或者发送wa
public class UserSendEmailObserver implements Observer{
@Override
public void notify(String message) {
System.out.println("用户注册成功,发送邮件通知!");
}
}
public class UserWaSendObserver implements Observer{
@Override
public void notify(String message) {
System.out.println("用户注册成功,发送了wa通知");
}
}
最终的Demo 其实就是这样,将观察者添加到被观察者上,观察者一旦执行了用户注册,就会触发对应动作,比如说新增新的动作,那么就可以直接添加一个发优惠卷的观察者。可以很好的进行拓展。
public static void main(String[] args) {
UserSendEmailObserver userSendEmailObserver = new UserSendEmailObserver();
UserWaSendObserver userWaSendObserver = new UserWaSendObserver();
ConcreteSubject concreteSubject = new ConcreteSubject();
concreteSubject.registerObserver(userSendEmailObserver);
concreteSubject.registerObserver(userWaSendObserver);
concreteSubject.notifyObservers("register");
}
Spring 中如何应用观察者模式
在spring源码中,IOC容器进行初始化的过程中,refresh
() 方法中就包含观察者模式。而Spring进行了抽象,也就是将观察者和被观察者 进行调整成多播器和监听器,通过事件来驱动监听器的执行。
可以看到,整体的流程就是,初始化多播器对象,SimpleApplicationEventMulticaster
,将监听器添加到多播器中。然后发布事件,调用监听器进行处理。可以发现其实设计模式在实际的应用中,思想相同的,但是落地的时候都有自己的调整。本质上还是当多个对象所依赖的对象有对应的事件时,需要做对应的动作。解耦合观察者和被观察者。
//初始化事件多播功能(事件派发) Initialize event multicaster for this context.
//初始化多播器 SimpleApplicationEventMulticaster 注册到IOC容器中
initApplicationEventMulticaster();
//注册监听器,从容器中获取所有的ApplicationListener;
// Check for listener beans and register them.
registerListeners();
//发布事件 Last step: publish corresponding event.
finishRefresh();