返回
巧妙学习设计模式:跟随 Guava 和 Spring 轻松掌握观察者模式
后端
2023-10-20 06:37:01
观察者模式:了解对象之间的灵活通信
想象这样一个场景:一群朋友聚在一起看电影。其中一位朋友拿起遥控器换台时,所有其他朋友都跟着换台了。这是因为他们都订阅了同一个“电视遥控器”主题。这就是观察者模式的本质,它允许对象在不知道其他对象的情况下进行通信。
观察者模式的魔力
观察者模式是一项卓越的设计模式,它可以让对象在松散耦合的情况下进行交互。这使得代码更容易维护,并提高了应用程序的性能。
在观察者模式中,有两个关键参与者:
- 被观察者(Subject): 发布事件或状态变化的对象。
- 观察者(Observer): 订阅特定事件或状态变化的对象。
被观察者维护一个观察者列表,每当它的状态发生变化时,它都会通知所有观察者。观察者可以是任何对象,只要它们实现了观察者接口。
Guava 的观察者模式
Guava 是一个流行的 Java 库,它提供了对观察者模式的强大支持。Guava 使用事件监听器来通知观察者。要使用 Guava 的观察者模式,需要创建以下对象:
- Observable(被观察者): 实现 Observable 接口,提供 addObserver() 和 notifyObservers() 方法。
- Observer(观察者): 实现 Observer 接口,提供 update() 方法来处理事件。
Spring 的观察者模式
Spring 是另一个备受推崇的 Java 框架,它也提供了观察者模式的实现。Spring 使用事件发布器和事件监听器来实现该模式。要使用 Spring 的观察者模式,需要创建以下对象:
- ApplicationEventPublisher(事件发布器): 实现 ApplicationEventPublisher 接口,提供 publishEvent() 方法。
- ApplicationListener(事件监听器): 实现 ApplicationListener 接口,提供 onApplicationEvent() 方法来处理事件。
观察者模式的优势
观察者模式提供了许多优势,包括:
- 松散耦合: 观察者和被观察者之间的交互是松散耦合的,这意味着可以轻松地添加或删除观察者而不会影响其他对象。
- 更好的维护性: 松散耦合可以简化代码维护,因为更改被观察者不会影响观察者,反之亦然。
- 提高性能: 观察者只会在被观察者状态发生变化时才被通知,这可以显著提高应用程序的性能。
代码示例
// Guava 的观察者模式
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
public class GuavaObserverPattern {
public static void main(String[] args) {
EventBus eventBus = new EventBus();
Subject subject = new Subject();
Observer observer1 = new Observer1();
Observer observer2 = new Observer2();
eventBus.register(observer1);
eventBus.register(observer2);
subject.setState(10);
eventBus.post(subject);
}
public static class Subject {
private int state;
public void setState(int state) {
this.state = state;
}
}
public static class Observer1 {
@Subscribe
public void update(Subject subject) {
System.out.println("Observer1: " + subject.state);
}
}
public static class Observer2 {
@Subscribe
public void update(Subject subject) {
System.out.println("Observer2: " + subject.state);
}
}
}
// Spring 的观察者模式
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
public class SpringObserverPattern {
public static void main(String[] args) {
ApplicationEventPublisher publisher = ...;
Subject subject = new Subject();
Observer observer1 = new Observer1();
Observer observer2 = new Observer2();
publisher.addApplicationListener(observer1);
publisher.addApplicationListener(observer2);
subject.setState(10);
publisher.publishEvent(new SubjectEvent(subject));
}
public static class Subject {
private int state;
public void setState(int state) {
this.state = state;
}
}
public static class Observer1 {
@EventListener
public void handleEvent(SubjectEvent event) {
System.out.println("Observer1: " + event.getSubject().state);
}
}
public static class Observer2 {
@EventListener
public void handleEvent(SubjectEvent event) {
System.out.println("Observer2: " + event.getSubject().state);
}
}
public static class SubjectEvent extends ApplicationEvent {
private Subject subject;
public SubjectEvent(Subject subject) {
super(subject);
this.subject = subject;
}
public Subject getSubject() {
return subject;
}
}
}
常见问题解答
-
观察者模式有什么局限性吗?
- 观察者模式可能会引入循环依赖,因此必须小心管理观察者和被观察者的关系。
-
如何防止观察者耦合到被观察者的实现中?
- 使用接口或抽象类来定义观察者和被观察者之间的通信接口。
-
如何处理多个被观察者?
- 使用事件总线或发布/订阅系统来同时管理多个被观察者。
-
观察者模式适用于哪些情况?
- 当需要通知多个对象时,观察者模式是一个很好的选择,例如用户界面更新、数据更改和事件处理。
-
有哪些替代观察者模式的模式?
- 中介者模式和发布/订阅模式是观察者模式的替代方案,可以根据具体情况选择使用。