You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Observer Pattern:初始化观察者时被观察者未存在的替代实现方案

观察者模式中被观察者晚于观察者创建的替代实现

当观察者初始化时被观察者还未创建,你可以用以下几种实用方案来实现延迟关联:

1. 手动延迟注册

这是最直接的方式:先实例化观察者,等被观察者创建完成后,手动调用被观察者的注册方法完成绑定。

// 观察者实现
public class ConcreteObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到更新通知: " + arg);
    }
}

// 被观察者实现
public class ConcreteObservable extends Observable {
    public void performAction() {
        setChanged();
        notifyObservers("动作执行完毕");
    }
}

// 业务逻辑调用
public class Application {
    public static void main(String[] args) {
        // 先创建观察者
        ConcreteObserver observer = new ConcreteObserver();
        
        // 后续在合适时机创建被观察者
        ConcreteObservable observable = new ConcreteObservable();
        
        // 手动完成注册
        observable.addObserver(observer);
        
        // 触发通知
        observable.performAction();
    }
}

优点:逻辑简单直观,无额外依赖;缺点:需要手动管控注册时机,大型系统中容易遗漏或出错。

2. 注册队列中介类

创建一个中介类来缓存等待注册的观察者,当被观察者创建完成后,自动将所有缓存的观察者批量注册到被观察者上。适合需要批量管理观察者的场景。

import java.util.ArrayList;
import java.util.List;

// 注册中介
public class ObserverMediator {
    private static List<Observer> waitingObservers = new ArrayList<>();
    private static ConcreteObservable targetObservable;

    // 注册待绑定的观察者
    public static void registerWaitingObserver(Observer observer) {
        if (targetObservable != null) {
            targetObservable.addObserver(observer);
        } else {
            waitingObservers.add(observer);
        }
    }

    // 设置被观察者并完成批量注册
    public static void bindObservable(ConcreteObservable observable) {
        targetObservable = observable;
        waitingObservers.forEach(observable::addObserver);
        waitingObservers.clear();
    }
}

// 调用逻辑
public class Application {
    public static void main(String[] args) {
        // 提前创建观察者并注册到中介
        ConcreteObserver observer1 = new ConcreteObserver();
        ObserverMediator.registerWaitingObserver(observer1);
        
        ConcreteObserver observer2 = new ConcreteObserver();
        ObserverMediator.registerWaitingObserver(observer2);
        
        // 创建被观察者并通知中介完成绑定
        ConcreteObservable observable = new ConcreteObservable();
        ObserverMediator.bindObservable(observable);
        
        observable.performAction();
    }
}

优点:自动处理注册时机,无需逐个手动绑定;缺点:引入了中介类,增加了系统的复杂度,若使用全局单例需注意线程安全问题。

3. 事件总线解耦方案

用事件总线替代传统的观察者模式,观察者订阅指定事件类型,被观察者发布事件,两者完全解耦,无需关注对方的创建顺序。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 简易事件总线
public class EventBus {
    private static Map<Class<?>, List<EventListener<?>>> listenerMap = new HashMap<>();

    // 订阅事件
    @SuppressWarnings("unchecked")
    public static <T> void subscribe(Class<T> eventType, EventListener<T> listener) {
        listenerMap.computeIfAbsent(eventType, k -> new ArrayList<>()).add(listener);
    }

    // 发布事件
    @SuppressWarnings("unchecked")
    public static <T> void publish(T event) {
        List<EventListener<?>> listeners = listenerMap.get(event.getClass());
        if (listeners != null) {
            for (EventListener<?> listener : listeners) {
                ((EventListener<T>) listener).onEvent(event);
            }
        }
    }

    // 事件监听器接口
    public interface EventListener<T> {
        void onEvent(T event);
    }
}

// 自定义事件
public class ActionCompletedEvent {
    private String detail;

    public ActionCompletedEvent(String detail) {
        this.detail = detail;
    }

    public String getDetail() {
        return detail;
    }
}

// 观察者(事件订阅者)
public class EventBasedObserver implements EventBus.EventListener<ActionCompletedEvent> {
    @Override
    public void onEvent(ActionCompletedEvent event) {
        System.out.println("收到事件通知: " + event.getDetail());
    }
}

// 被观察者(事件发布者)
public class EventPublisher {
    public void performAction() {
        EventBus.publish(new ActionCompletedEvent("动作执行完毕"));
    }
}

// 调用逻辑
public class Application {
    public static void main(String[] args) {
        // 提前创建观察者并订阅事件
        EventBasedObserver observer = new EventBasedObserver();
        EventBus.subscribe(ActionCompletedEvent.class, observer);
        
        // 后续创建事件发布者
        EventPublisher publisher = new EventPublisher();
        
        // 发布事件
        publisher.performAction();
    }
}

优点:彻底解耦观察者与被观察者,无需关心对方的生命周期;缺点:需要实现或引入事件总线组件,小型项目可能显得冗余。

4. 懒加载被观察者引用

在观察者中持有被观察者的弱引用(避免内存泄漏),后续通过方法设置被观察者并完成注册,适合观察者可能动态关联不同被观察者的场景。

import java.lang.ref.WeakReference;
import java.util.Observable;
import java.util.Observer;

public class LazyBindingObserver implements Observer {
    private WeakReference<ConcreteObservable> observableRef;

    // 初始化时不绑定被观察者
    public LazyBindingObserver() {}

    // 后续绑定被观察者并注册
    public void bindToObservable(ConcreteObservable observable) {
        this.observableRef = new WeakReference<>(observable);
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("收到更新通知: " + arg);
    }
}

// 调用逻辑
public class Application {
    public static void main(String[] args) {
        LazyBindingObserver observer = new LazyBindingObserver();
        
        // 后续创建被观察者并完成绑定
        ConcreteObservable observable = new ConcreteObservable();
        observer.bindToObservable(observable);
        
        observable.performAction();
    }
}

优点:观察者可以独立初始化,后续灵活绑定被观察者;缺点:需要手动触发绑定操作,若遗漏则无法接收通知。

内容的提问来源于stack exchange,提问作者dev1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:33:33