返回

巧妙学习设计模式:跟随 Guava 和 Spring 轻松掌握观察者模式

后端

观察者模式:了解对象之间的灵活通信

想象这样一个场景:一群朋友聚在一起看电影。其中一位朋友拿起遥控器换台时,所有其他朋友都跟着换台了。这是因为他们都订阅了同一个“电视遥控器”主题。这就是观察者模式的本质,它允许对象在不知道其他对象的情况下进行通信。

观察者模式的魔力

观察者模式是一项卓越的设计模式,它可以让对象在松散耦合的情况下进行交互。这使得代码更容易维护,并提高了应用程序的性能。

在观察者模式中,有两个关键参与者:

  • 被观察者(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;
        }
    }
}

常见问题解答

  1. 观察者模式有什么局限性吗?

    • 观察者模式可能会引入循环依赖,因此必须小心管理观察者和被观察者的关系。
  2. 如何防止观察者耦合到被观察者的实现中?

    • 使用接口或抽象类来定义观察者和被观察者之间的通信接口。
  3. 如何处理多个被观察者?

    • 使用事件总线或发布/订阅系统来同时管理多个被观察者。
  4. 观察者模式适用于哪些情况?

    • 当需要通知多个对象时,观察者模式是一个很好的选择,例如用户界面更新、数据更改和事件处理。
  5. 有哪些替代观察者模式的模式?

    • 中介者模式和发布/订阅模式是观察者模式的替代方案,可以根据具体情况选择使用。