原理
观察者模式属于行为模式,行为模式主要解决类和对象之间交互问题。
含义:在对象之间定义一个一对多的依赖,当一个对象状态改变时,所有依赖的对象会自动通知。
被依赖的对象被观察者(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<>();@Overridepublic void registerObserver(Observer observer) {observerList.add(observer);}@Overridepublic void deleteObserver(Observer observer) {observerList.remove(observer);}@Overridepublic 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{@Overridepublic void notify(String message) {System.out.println("用户注册成功,发送邮件通知!");}}public class UserWaSendObserver implements Observer{@Overridepublic 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();