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
相关产品推荐
相关产品推荐

