概念
观察者设计模式(Observer Design Pattern)是一种行为型设计模式,它定义了一种对象间的一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,通知所有观察者对象,使它们能够自动更新。
组成角色
- 主题(Subject):主题是一个抽象类或接口,它定义了添加、删除和通知观察者的方法。
- 具体主题(ConcreteSubject):具体主题是主题接口的实现,它包含观察者列表和业务逻辑。当状态发生改变时,具体主题负责通知所有观察者。
- 观察者(Observer):观察者是一个抽象类或接口,它定义了一个更新方法,用于接收主题的通知。
- 具体观察者(ConcreteObserver):具体观察者是观察者接口的实现,它根据主题的通知来更新自己的状态。
相关图示
示例代码
这个代码示例展示了观察者设计模式的基本实现。具体主题ConcreteSubject
存储了观察者列表和当前状态,当状态发生改变时,它会通知所有注册的观察者。观察者ConcreteObserverA
和ConcreteObserverB
实现了观察者接口Observer
,并在更新状态时输出相应的消息。在main
方法中,我们创建了一个具体主题和两个具体观察者,将观察者添加到主题中,然后改变主题的状态并观察输出结果。当从主题中移除一个观察者后,再次改变主题状态,可以看到只有剩下的观察者接收到了通知。
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
// 添加观察者
void addObserver(Observer observer);
// 移除观察者
void removeObserver(Observer observer);
// 通知所有观察者
void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
// 存储观察者的列表
private List<Observer> observers = new ArrayList<>();
// 主题的状态
private String state;
// 设置状态并通知所有观察者
public void setState(String state) {
this.state = state;
notifyObservers();
}
// 添加观察者到列表
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
// 从列表中移除观察者
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
// 通知所有观察者状态已改变
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 观察者接口
interface Observer {
// 更新观察者状态
void update(String state);
}
// 具体观察者A
class ConcreteObserverA implements Observer {
// 当收到主题通知时,更新状态
@Override
public void update(String state) {
System.out.println("ConcreteObserverA received new state: " + state);
}
}
// 具体观察者B
class ConcreteObserverB implements Observer {
// 当收到主题通知时,更新状态
@Override
public void update(String state) {
System.out.println("ConcreteObserverB received new state: " + state);
}
}
public class ObserverDemo {
public static void main(String[] args) {
// 创建具体主题
ConcreteSubject subject = new ConcreteSubject();
// 创建具体观察者A和B
ConcreteObserverA observerA = new ConcreteObserverA();
ConcreteObserverB observerB = new ConcreteObserverB();
// 向主题添加观察者A和B
subject.addObserver(observerA);
subject.addObserver(observerB);
// 改变主题状态并通知观察者
subject.setState("New state 1");
subject.setState("New state 2");
// 从主题中移除观察者A
subject.removeObserver(observerA);
// 再次改变主题状态并通知观察者
subject.setState("New state 3");
}
}
运行结果
框架中的运用
在Spring框架中,观察者模式主要应用在事件处理机制中。Spring监听器主要涉及到以下几个构成部分:
- ApplicationEvent(事件):
ApplicationEvent
是Spring中所有事件的基类,它继承自java.util.EventObject
。自定义事件需要继承ApplicationEvent
。当某个特定操作发生时,可以创建一个自定义的ApplicationEvent
实例,并将其发布到整个应用程序。 - ApplicationListener(监听器):
ApplicationListener
是一个泛型接口,泛型参数为继承自ApplicationEvent
的类。监听器负责监听特定类型的事件。实现ApplicationListener
接口的类需要实现onApplicationEvent()
方法以处理对应的事件。当一个事件被发布时,关注该事件的监听器会收到通知,并执行onApplicationEvent()
方法来处理事件。 - ApplicationEventPublisher(事件发布器):
ApplicationEventPublisher
是一个接口,负责发布事件。它提供了publishEvent()
方法,用于发布事件到整个应用程序。在Spring中,ApplicationContext
实现了ApplicationEventPublisher
接口,因此事件发布主要由ApplicationContext
管理。 - ApplicationEventMulticaster(事件多播器):
ApplicationEventMulticaster
是一个接口,负责将事件分发给关联的监听器。SimpleApplicationEventMulticaster
是ApplicationEventMulticaster
的一个默认实现。在Spring中,ApplicationEventMulticaster
负责管理所有注册的ApplicationListener
。当ApplicationEventPublisher
发布事件时,ApplicationEventMulticaster
会将事件分发给所有关注该事件的监听器。
-
org.springframework.context.ApplicationEvent
:
ApplicationEvent
是Spring事件模型的基类,它继承了java.util.EventObject
。所有自定义事件需要继承ApplicationEvent
类。
package org.springframework.context;
import java.util.EventObject;
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;
}
}
-
org.springframework.context.ApplicationListener
:
ApplicationListener
是一个泛型接口,它的泛型参数是一个继承自ApplicationEvent
的类。它类似于观察者模式中的观察者。实现ApplicationListener
接口的类需要实现onApplicationEvent()
方法以处理事件。
package org.springframework.context;
import java.util.EventListener;
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
-
org.springframework.context.ApplicationEventPublisher
:
ApplicationEventPublisher
接口负责发布事件。它类似于观察者模式中的主题。实现该接口的类需要实现publishEvent()
方法来发布事件。
package org.springframework.context;
public interface ApplicationEventPublisher {
void publishEvent(ApplicationEvent event);
void publishEvent(Object event);
}
-
org.springframework.context.event.SimpleApplicationEventMulticaster
:
SimpleApplicationEventMulticaster
是ApplicationEventMulticaster
接口的一个实现。它负责将事件分发给关联的监听器。其主要方法是multicastEvent(ApplicationEvent)
,该方法会遍历注册的监听器,并将事件分发给匹配的监听器。
package org.springframework.context.event;
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
// ...
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
} else {
invokeListener(listener, event);
}
}
}
// ...
}
-
org.springframework.context.support.AbstractApplicationContext
:
AbstractApplicationContext
实现了ApplicationEventPublisher
接口,因此在Spring中,事件发布主要由ApplicationContext
管理。AbstractApplicationContext
中的publishEvent(ApplicationEvent)
方法会委托给ApplicationEventMulticaster
进行事件的发布。
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
// ...
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
@Override
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
} else {
getApplicationEventMulticaster().multicastEvent(applicationEvent,
eventType);
}
// 发布事件给父级 ApplicationContext
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
}
// ...
总之大概的逻辑是这样
-
创建自定义事件
CustomEvent
,该事件需要继承ApplicationEvent
。 -
创建自定义事件监听器
CustomEventListener
,该监听器需要实现ApplicationListener<CustomEvent>
接口。 -
在需要的地方使用
ApplicationEventPublisher
(通常是ApplicationContext
)发布事件。在AbstractApplicationContext
中,publishEvent
方法会将事件委托给ApplicationEventMulticaster
进行发布。 -
SimpleApplicationEventMulticaster
(默认的ApplicationEventMulticaster
实现)会将事件分发给关联的监听器。在multicastEvent
方法中,它会遍历所有注册的监听器,并将事件分发给匹配的监听器。 -
监听器收到事件后,将执行
onApplicationEvent()
方法处理事件。文章来源:https://www.toymoban.com/news/detail-424092.html
通过上述流程,我们可以看到Spring监听器执行原理是基于观察者设计模式的。当事件发布后,所有关注该事件的监听器都会收到通知并执行相应的操作。这种机制实现了松耦合的事件处理,可以在不同组件之间实现动态交互。文章来源地址https://www.toymoban.com/news/detail-424092.html
适用场景
- 事件处理系统:观察者模式可以用于实现事件驱动的架构,当一个事件发生时,所有关心这个事件的观察者都会收到通知。这在GUI开发、游戏开发等场景中非常常见。
- 数据绑定和同步:当多个组件需要共享或同步相同的数据时,可以使用观察者模式。当数据发生变化时,所有依赖于该数据的观察者都会收到通知并自动更新。这在前端开发、实时协同编辑等场景中非常有用。
- 消息发布和订阅:观察者模式可以用于实现发布/订阅系统。在这种系统中,发布者负责发布消息,订阅者负责订阅消息。当发布者发布新消息时,所有订阅了该消息的订阅者都会收到通知。这在分布式系统、消息队列、事件总线等场景中非常常见。
- 状态监控和报警:在系统监控和报警场景中,观察者模式可以用于实时监控被观察对象的状态。当被观察对象的状态发生异常时,观察者可以根据预定义的规则执行相应的操作,如发送报警邮件、记录日志等。
到了这里,关于观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!