Java 观察者模式 3 种实现对比原生接口 vs 自定义 vs Spring 事件机制在软件开发中对象间的状态同步是个永恒话题。想象这样一个场景当电商平台的商品价格变动时需要实时通知库存系统、促销系统和用户终端。如果采用硬编码方式逐个调用系统将变得僵化且难以维护。观察者模式正是为解决这类问题而生它让对象间的状态同步变得优雅而灵活。Java 生态提供了多种实现观察者模式的方式从早期的java.util.Observable到 Spring 框架的事件机制每种方案都有其适用场景和独特优势。本文将深入剖析三种典型实现通过代码示例和对比表格帮助开发者根据项目需求做出合理选择。1. 原生 JDK 观察者接口实现Java 从早期版本就内置了观察者模式的实现通过java.util.Observable类和Observer接口提供基础支持。虽然这两个类在 Java 9 后被标记为废弃但其设计思想仍值得学习。典型实现步骤// 继承Observable实现被观察者 class ProductPrice extends Observable { private String name; private double price; public void setPrice(double newPrice) { if (this.price ! newPrice) { this.price newPrice; setChanged(); // 标记状态变更 notifyObservers(price); // 推送新价格 } } } // 实现Observer接口的观察者 class PriceAlert implements Observer { Override public void update(Observable o, Object arg) { if (o instanceof ProductPrice) { System.out.printf(价格警报商品 %s 新价格为 %.2f%n, ((ProductPrice)o).getName(), (Double)arg); } } }使用示例ProductPrice product new ProductPrice(iPhone14); product.addObserver(new PriceAlert()); product.setPrice(5999.00); // 触发通知关键特点内置线程安全Observable的方法都使用synchronized修饰推拉结合模型可通过notifyObservers(arg)推送数据观察者也可主动调用被观察者方法获取状态缺点明显被观察者必须继承ObservableJava 的单继承限制设计灵活性通知顺序不可控缺乏对异常处理的统一支持提示在 Java 9 环境中建议使用PropertyChangeListener替代Observer接口或直接采用自定义实现。2. 自定义观察者模式实现当需要更灵活的设计时自定义实现是更好的选择。典型方案是定义Subject和Observer接口建立完全可控的观察机制。基础实现代码// 观察者接口 interface StockObserver { void update(String symbol, double price); } // 被观察者抽象类 abstract class StockSubject { private ListStockObserver observers new ArrayList(); public void addObserver(StockObserver o) { observers.add(o); } protected void notifyObservers(String symbol, double price) { observers.forEach(o - o.update(symbol, price)); } } // 具体被观察者 class StockMarket extends StockSubject { private MapString, Double stocks new HashMap(); public void setPrice(String symbol, double price) { stocks.put(symbol, price); notifyObservers(symbol, price); } }高级特性扩展// 支持优先级排序的观察者列表 class PriorityStockSubject { private PriorityQueueStockObserver queue new PriorityQueue(Comparator.comparingInt(StockObserver::getPriority)); void notifyObservers(String symbol, double price) { while (!queue.isEmpty()) { queue.poll().update(symbol, price); } } } // 异步通知实现 class AsyncNotifier { private Executor executor Executors.newCachedThreadPool(); void safeNotify(StockObserver o, String symbol, double price) { executor.execute(() - { try { o.update(symbol, price); } catch (Exception e) { log.error(通知观察者失败, e); } }); } }优势对比特性JDK 原生实现自定义实现继承灵活性低需继承Observable高接口实现线程控制内置同步可能成为瓶颈可自由选择同步策略通知顺序不可控可自定义排序异常处理无保护可定制异常处理扩展性低高支持过滤、转换等3. Spring 事件机制实现在 Spring 框架中观察者模式通过事件机制得到全面提升成为应用内通信的重要方式。其核心由三个部分组成核心组件ApplicationEvent所有事件的基类ApplicationListener观察者接口ApplicationEventPublisher事件发布接口典型实现示例// 自定义事件 class OrderCreatedEvent extends ApplicationEvent { private String orderId; public OrderCreatedEvent(Object source, String orderId) { super(source); this.orderId orderId; } } // 事件监听器方式一 Component class OrderNotificationListener implements ApplicationListenerOrderCreatedEvent { Override Async // 支持异步处理 public void onApplicationEvent(OrderCreatedEvent event) { sendSMS(event.getOrderId()); } } // 事件监听器方式二注解方式 Component class OrderAuditListener { EventListener Order(1) // 指定处理顺序 public void auditOrder(OrderCreatedEvent event) { log.info(订单创建审计: {}, event.getOrderId()); } } // 事件发布 Service class OrderService { Autowired private ApplicationEventPublisher publisher; public void createOrder(Order order) { // 创建订单逻辑... publisher.publishEvent(new OrderCreatedEvent(this, order.getId())); } }Spring 事件机制优势与容器深度集成自动处理监听器的注册和依赖注入丰富的扩展点支持同步/异步处理通过Async支持事件处理顺序控制Order支持事务绑定事件TransactionalEventListener强大的过滤能力可通过 SpEL 表达式定义触发条件与响应式编程结合支持 Reactive Stream 的事件处理4. 三种实现方案综合对比为帮助开发者选择合适的实现方案我们从六个维度进行系统对比对比维度JDK 原生实现自定义实现Spring 事件机制耦合度较高继承强耦合低接口松耦合最低完全解耦功能完整性基础功能可自由扩展企业级功能性能表现同步阻塞可异步优化支持异步/同步学习成本低中等较高框架依赖无无需 Spring 环境适用场景简单桌面应用需要定制的业务场景Spring 生态项目选型建议遗留系统维护可继续使用 JDK 原生实现但建议逐步迁移性能敏感场景选择自定义实现精确控制通知逻辑和线程模型Spring 项目优先采用 Spring 事件机制享受容器管理优势复杂事件处理考虑结合 Spring Cloud Stream 或 Reactor 等响应式框架5. 高级应用与最佳实践观察者模式在实际应用中还有许多值得注意的细节和技巧线程安全实现方案// 使用 CopyOnWriteArrayList 实现线程安全的观察者列表 class ConcurrentSubject { private final ListObserver observers new CopyOnWriteArrayList(); public void addObserver(Observer o) { observers.add(Objects.requireNonNull(o)); } public void notifyObservers(Event event) { for (Observer o : observers) { o.onEvent(event); } } }防止内存泄漏// 使用弱引用持有观察者 class WeakRefSubject { private final ListWeakReferenceObserver observers new ArrayList(); public void addObserver(Observer o) { observers.add(new WeakReference(o)); } public void notifyObservers() { IteratorWeakReferenceObserver it observers.iterator(); while (it.hasNext()) { Observer o it.next().get(); if (o ! null) { o.update(); } else { it.remove(); // 清理已被GC的观察者 } } } }性能优化技巧批量通知对高频事件进行合并处理class BatchEventPublisher { private final BlockingQueueEvent queue new LinkedBlockingQueue(); private final ScheduledExecutorService scheduler Executors.newSingleThreadScheduledExecutor(); public BatchEventPublisher() { scheduler.scheduleAtFixedRate(this::publishBatch, 100, 100, MILLISECONDS); } private void publishBatch() { ListEvent events new ArrayList(); queue.drainTo(events); if (!events.isEmpty()) { notifyObservers(new BatchEvent(events)); } } }选择性通知根据观察者兴趣进行过滤interface InterestObserver { SetEventType getInterests(); void onEvent(Event event); } class SmartSubject { void notifyObserver(InterestObserver o, Event e) { if (o.getInterests().contains(e.getType())) { o.onEvent(e); } } }与其它模式的结合责任链模式让观察者形成处理链条class ChainableObserver implements Observer { private final Observer next; public void onEvent(Event e) { if (canHandle(e)) { handle(e); } else if (next ! null) { next.onEvent(e); } } }代理模式为观察者添加增强逻辑class ObservableProxy implements Observer { private final Observer target; public void onEvent(Event e) { long start System.nanoTime(); target.onEvent(e); log.debug(处理耗时: {}ns, System.nanoTime()-start); } }观察者模式作为解耦利器在现代Java开发中仍然充满活力。理解不同实现方案的特性根据项目需求灵活选择才能充分发挥其价值。