观察者模式

2021/10/02 JAVA8 共 2675 字,约 8 分钟
闷骚的程序员

1. jdk原生的观察者模式过时了

在 JDK 中,观察者模式的相关接口和类是 java.util.Observerjava.util.Observable,它们从 JDK 9 开始被标记为 @Deprecated,但并未被彻底移除。以下是被标记为过时的原因以及如何替代它们。


为什么 ObserverObservable 被标记为过时?

  1. 不符合现代设计理念
    • Observable 是一个类,而不是接口,这限制了扩展性。
    • 现代设计更倾向于通过接口来定义行为,使得类可以自由组合多个功能,而不是被强制继承一个具体的实现。
  2. 线程安全问题
    • Observable 的方法没有明确的线程安全保证,特别是在多线程环境中操作 Observable 时可能会导致并发问题,例如在添加或删除观察者时。
  3. 不够灵活
    • Observable 的实现过于简单,难以满足复杂的需求。例如,它不支持细粒度的通知机制,也无法方便地处理特定的订阅者群体。
  4. 与流式 API 和响应式编程的不兼容
    • JDK 自从引入了 java.util.stream 和响应式框架(如 java.util.concurrent.Flow),提供了更强大、更现代的方式来实现观察者模式。这些方式更灵活,且与其他现代 API 更兼容。

有没有被废除?

虽然 ObserverObservable 被标记为过时(@Deprecated),但它们依然存在于 JDK 中,并未被彻底移除。这意味着现有的代码仍然可以使用它们,但建议避免在新代码中继续使用。


替代方案

  1. 使用 java.util.concurrent.Flow
    从 JDK 9 开始,Java 提供了 java.util.concurrent.Flow 类来支持响应式流(Reactive Streams),这是实现观察者模式的现代方式。它包含以下主要接口:
    • Flow.Publisher
    • Flow.Subscriber
    • Flow.Processor

    示例

    import java.util.concurrent.Flow;
    import java.util.concurrent.SubmissionPublisher;
    
    public class ObserverExample {
        public static void main(String[] args) throws InterruptedException {
            SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
            Flow.Subscriber<String> subscriber = new Flow.Subscriber<>() {
                private Flow.Subscription subscription;
    
                @Override
                public void onSubscribe(Flow.Subscription subscription) {
                    this.subscription = subscription;
                    subscription.request(1);
                }
    
                @Override
                public void onNext(String item) {
                    System.out.println("Received: " + item);
                    subscription.request(1);
                }
    
                @Override
                public void onError(Throwable throwable) {
                    System.err.println("Error: " + throwable.getMessage());
                }
    
                @Override
                public void onComplete() {
                    System.out.println("Done");
                }
            };
    
            publisher.subscribe(subscriber);
            publisher.submit("Hello");
            publisher.submit("World");
            publisher.close();
    
            Thread.sleep(100); // 等待订阅者处理完毕
        }
    }
    
  2. 使用第三方库(如 RxJava 或 Project Reactor)
    如果需要更强大的响应式编程功能,可以使用第三方库:
    • RxJava:流行的响应式扩展库。
    • Project Reactor:Spring 框架的响应式编程核心库。
  3. 手动实现观察者模式
    可以根据项目需求手动实现一个简单而灵活的观察者模式。
    import java.util.ArrayList;
    import java.util.List;
    
    interface Observer {
        void update(String message);
    }
    
    class Subject {
        private final List<Observer> observers = new ArrayList<>();
    
        public void addObserver(Observer observer) {
            observers.add(observer);
        }
    
        public void removeObserver(Observer observer) {
            observers.remove(observer);
        }
    
        public void notifyObservers(String message) {
            for (Observer observer : observers) {
                observer.update(message);
            }
        }
    }
    
    public class CustomObserverExample {
        public static void main(String[] args) {
            Subject subject = new Subject();
    
            Observer observer1 = msg -> System.out.println("Observer 1 received: " + msg);
            Observer observer2 = msg -> System.out.println("Observer 2 received: " + msg);
    
            subject.addObserver(observer1);
            subject.addObserver(observer2);
    
            subject.notifyObservers("Hello Observers!");
        }
    }
    

总结

虽然 java.util.Observerjava.util.Observable 并未被彻底移除,但它们已经过时,主要因为它们设计不灵活、缺乏线程安全性以及无法适应现代编程需求。在新项目中,推荐使用 Flow API 或响应式编程框架(如 RxJava 或 Reactor)来实现观察者模式。

文档信息

Search

    Table of Contents