news 2026/7/15 6:46:43

设计模式第5讲——观察者模式(Observer)在现代化架构中的演进与实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式第5讲——观察者模式(Observer)在现代化架构中的演进与实践

1. 观察者模式基础概念

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一对多依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式也被称为"发布-订阅"模式(Publish-Subscribe),是解耦系统组件的重要工具。

想象一下报纸订阅的场景:报社(被观察者)每天发布新报纸,订阅者(观察者)会自动收到最新报纸。在这个过程中,报社不需要知道具体有哪些订阅者,订阅者也无需主动询问是否有新报纸。这种松耦合的设计正是观察者模式的核心价值。

观察者模式包含四个关键角色:

  • 抽象主题(Subject):定义添加、删除观察者及通知观察者的接口
  • 具体主题(ConcreteSubject):维护观察者列表,状态改变时通知所有观察者
  • 抽象观察者(Observer):定义更新接口,用于接收主题通知
  • 具体观察者(ConcreteObserver):实现更新接口,保持与主题状态的一致性

2. 传统实现与现代化演进

2.1 经典Java实现

在传统Java实现中,我们通常会定义Subject和Observer接口:

// 抽象主题 interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } // 抽象观察者 interface Observer { void update(Subject subject); }

具体主题维护观察者列表并在状态变化时通知:

class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<>(); private int state; public void setState(int state) { this.state = state; notifyObservers(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void notifyObservers() { for (Observer o : observers) { o.update(this); } } }

2.2 JDK内置支持

Java标准库提供了Observable类和Observer接口:

import java.util.Observable; import java.util.Observer; class WeatherData extends Observable { private float temperature; public void measurementsChanged() { setChanged(); // 标记状态已改变 notifyObservers(); // 通知观察者 } public void setMeasurements(float temp) { this.temperature = temp; measurementsChanged(); } } class CurrentConditionsDisplay implements Observer { @Override public void update(Observable o, Object arg) { if (o instanceof WeatherData) { // 处理更新逻辑 } } }

虽然JDK提供了现成实现,但在现代Java开发中更推荐使用自定义接口,因为Observable是类而非接口,限制了复用性。

3. 现代分布式架构中的观察者模式

3.1 消息队列实现

在微服务架构中,观察者模式通常通过消息队列实现:

// 使用Spring AMQP实现 @Configuration public class RabbitConfig { @Bean public TopicExchange eventExchange() { return new TopicExchange("event-exchange"); } } @Service public class OrderService { @Autowired private RabbitTemplate rabbitTemplate; public void createOrder(Order order) { // 创建订单逻辑 rabbitTemplate.convertAndSend("event-exchange", "order.created", order); } } @Component public class NotificationService { @RabbitListener(bindings = @QueueBinding( value = @Queue("notification-queue"), exchange = @Exchange("event-exchange"), key = "order.created" )) public void handleOrderCreated(Order order) { // 发送通知 } }

这种实现方式解耦了服务间的直接调用,提高了系统的可扩展性和可靠性。

3.2 事件总线模式

现代框架如Spring提供了更高级的事件机制:

// 定义事件 public class OrderCreatedEvent { private final Order order; public OrderCreatedEvent(Order order) { this.order = order; } // getter } // 发布事件 @Service public class OrderService { @Autowired private ApplicationEventPublisher eventPublisher; public void createOrder(Order order) { // 创建订单逻辑 eventPublisher.publishEvent(new OrderCreatedEvent(order)); } } // 监听事件 @Component public class NotificationListener { @EventListener public void handleOrderCreated(OrderCreatedEvent event) { // 处理事件 } }

事件总线模式提供了类型安全的事件处理,同时保持了松耦合特性。

4. 云原生场景下的最佳实践

4.1 响应式编程实现

使用Reactor库实现响应式观察者:

public class StockPublisher { private final Flux<StockPrice> prices; public StockPublisher() { this.prices = Flux.interval(Duration.ofSeconds(1)) .map(i -> generateRandomPrice()) .publish() .autoConnect(); } public Flux<StockPrice> getPrices() { return prices; } } // 订阅使用 stockPublisher.getPrices() .subscribe(price -> System.out.println("Price update: " + price));

响应式流天然实现了观察者模式,支持背压等高级特性。

4.2 WebSocket实时通知

前端与后端的实时通信场景:

@RestController @RequestMapping("/notifications") public class NotificationController { private final SimpMessagingTemplate messagingTemplate; @PostMapping public void sendNotification(@RequestBody Notification notification) { messagingTemplate.convertAndSend( "/topic/notifications", notification ); } } // 前端JavaScript const socket = new SockJS('/ws'); const client = Stomp.over(socket); client.connect({}, () => { client.subscribe('/topic/notifications', (message) => { // 处理实时通知 }); });

这种模式广泛应用于实时仪表盘、聊天应用等场景。

5. 性能优化与常见陷阱

5.1 异步通知机制

同步通知可能导致性能瓶颈:

// 异步通知实现 class AsyncSubject implements Subject { private final Executor executor = Executors.newFixedThreadPool(4); private final List<Observer> observers = new CopyOnWriteArrayList<>(); public void notifyObservers() { for (Observer o : observers) { executor.execute(() -> o.update(this)); } } }

使用线程池和线程安全的集合类可以避免并发问题。

5.2 内存泄漏防护

观察者未正确注销会导致内存泄漏:

// 使用弱引用防止内存泄漏 class WeakRefSubject { private final List<WeakReference<Observer>> observers = new ArrayList<>(); public void addObserver(Observer o) { observers.add(new WeakReference<>(o)); } public void notifyObservers() { Iterator<WeakReference<Observer>> it = observers.iterator(); while (it.hasNext()) { Observer o = it.next().get(); if (o != null) { o.update(this); } else { it.remove(); // 清理已被GC的观察者 } } } }

5.3 分布式一致性挑战

在分布式系统中实现可靠事件传递:

// 使用事务发件箱模式 @Service @Transactional public class OrderService { @Autowired private OutboxRepository outbox; public void createOrder(Order order) { // 保存订单 orderRepository.save(order); // 写入发件箱 outbox.save(new OutboxEvent( "order.created", order.getId(), order )); } } // 单独进程处理发件箱 @Scheduled(fixedRate = 5000) public void processOutbox() { List<OutboxEvent> events = outbox.findUnprocessed(); events.forEach(event -> { rabbitTemplate.convertAndSend( "event-exchange", event.getType(), event.getPayload() ); event.markAsProcessed(); outbox.save(event); }); }

6. 行业应用案例分析

6.1 电商订单状态通知

典型电商系统中的观察者模式应用:

// 订单状态变更事件 public class OrderStatusEvent { private String orderId; private OrderStatus oldStatus; private OrderStatus newStatus; // getters & setters } // 多个监听器处理不同业务 @Component public class OrderStatusListener { @EventListener public void sendNotification(OrderStatusEvent event) { // 发送短信/邮件通知 } @EventListener public void updateInventory(OrderStatusEvent event) { if (event.getNewStatus() == OrderStatus.CANCELLED) { // 恢复库存 } } @EventListener @Async public void logAuditTrail(OrderStatusEvent event) { // 异步记录审计日志 } }

6.2 IoT设备状态监控

物联网设备状态监控场景:

// 设备状态主题 public class DeviceStateTopic { private final Map<String, List<Consumer<DeviceState>>> subscribers = new ConcurrentHashMap<>(); public void subscribe(String deviceId, Consumer<DeviceState> callback) { subscribers.computeIfAbsent(deviceId, k -> new ArrayList<>()) .add(callback); } public void publish(String deviceId, DeviceState state) { List<Consumer<DeviceState>> deviceSubscribers = subscribers.get(deviceId); if (deviceSubscribers != null) { deviceSubscribers.forEach(c -> c.accept(state)); } } } // 使用示例 deviceTopic.subscribe("sensor-001", state -> { if (state.getTemperature() > 50) { triggerAlarm(); } });

7. 模式变体与相关模式

7.1 事件溯源模式

事件溯源是观察者模式的进阶应用:

// 事件存储 public class EventStore { private final List<Event> events = new ArrayList<>(); private final List<Consumer<Event>> subscribers = new ArrayList<>(); public void append(Event event) { events.add(event); subscribers.forEach(s -> s.accept(event)); } public void subscribe(Consumer<Event> subscriber) { subscribers.add(subscriber); } } // 使用示例 eventStore.subscribe(event -> { if (event instanceof OrderCreated) { updateReadModel((OrderCreated)event); } });

7.2 中介者模式对比

中介者模式与观察者模式的区别:

  • 观察者:单向通信,主题不知道观察者如何响应
  • 中介者:集中式控制,协调多个对象间的交互
// 中介者示例 class ChatRoom { public static void showMessage(User user, String message) { System.out.println(user.getName() + ": " + message); } } // 用户只需与中介者交互 user1.sendMessage("Hi!"); // 内部调用ChatRoom.showMessage

8. 测试策略与调试技巧

8.1 单元测试观察者

使用Mock对象测试观察者交互:

@Test public void testObserverNotification() { // 创建mock观察者 Observer mockObserver = mock(Observer.class); // 创建主题并注册观察者 ConcreteSubject subject = new ConcreteSubject(); subject.registerObserver(mockObserver); // 改变状态触发通知 subject.setState(5); // 验证观察者被调用 verify(mockObserver).update(subject); }

8.2 集成测试事件流

测试完整事件处理流水线:

@SpringBootTest public class EventIntegrationTest { @Autowired private ApplicationEventPublisher publisher; @MockBean private NotificationService notificationService; @Test public void testOrderEventFlow() { Order order = new Order("test-order"); // 发布事件 publisher.publishEvent(new OrderCreatedEvent(order)); // 验证通知服务被调用 verify(notificationService, timeout(1000)) .sendOrderCreatedNotification(order); } }

9. 未来演进趋势

观察者模式在云原生时代的演进方向包括:

  • 服务网格中的全局事件总线
  • 基于WebAssembly的跨语言事件处理
  • 与AI结合的智能事件路由
  • 区块链环境中的去中心化观察者网络

这些趋势将继续扩展观察者模式的应用边界,使其在分布式系统架构中发挥更重要的作用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/15 6:45:58

鸿蒙打包、签名、加固、上架全流程实战(商用 APP 上线终极教程)

一、前言很多开发者可以顺利完成鸿蒙功能开发、UI适配、性能优化、隐私权限合规&#xff0c;但最终卡在打包报错、签名异常、上线审核驳回。对于商用、政企、银行级鸿蒙项目&#xff0c;能开发只是基础&#xff0c;能规范打包、安全加固、稳定上线交付才是职业化能力。日常开发…

作者头像 李华
网站建设 2026/7/15 6:41:08

VisualAD:抛弃文本分支!纯视觉零样本异常检测首次超越CLIP,CVPR2026

本文核心贡献如下: 挑战主流范式:首次系统论证零样本异常检测中文本分支并非必要,纯视觉即可学习判别性异常特征。 提出VisualAD框架:在冻结ViT中直接插入可学习的正常与异常标记,通过多层自注意力交互编码高层异常语义。 设计SCA+SAF模块:空间感知交叉注意力注入细粒度…

作者头像 李华
网站建设 2026/7/15 6:40:52

新能源领涨,西藏矿业涨停

A股早间速览&#xff1a;4月2日市场数据报告 一、大盘指数表现 截至4月2日收盘&#xff0c;A股三大指数集体下跌&#xff0c;市场整体呈现调整态势。具体数据如下&#xff1a; 上证指数&#xff1a;报3919.29点&#xff0c;跌幅 -0.74% 。深证成指&#xff1a;报13486.94点&…

作者头像 李华
网站建设 2026/7/15 6:39:01

高性能LDO电源设计实战:从TPS7A83A外围电路到噪声与PSRR优化

1. 项目概述&#xff1a;为什么我们需要一颗“安静”且“可靠”的LDO&#xff1f;在任何一个电子系统中&#xff0c;电源就像心脏&#xff0c;为各个功能模块输送能量。但并非所有“血液”都是纯净的&#xff0c;电源线上的噪声、纹波和电压波动&#xff0c;对于模拟前端、高速…

作者头像 李华
网站建设 2026/7/15 6:37:53

如何在《欧洲卡车模拟2》中实现5分钟快速部署自动驾驶辅助系统

如何在《欧洲卡车模拟2》中实现5分钟快速部署自动驾驶辅助系统 【免费下载链接】ETS2LA Plugin based interface program for ETS2/ATS. 项目地址: https://gitcode.com/gh_mirrors/eur/ETS2LA ETS2LA是一个为《欧洲卡车模拟2》和《美国卡车模拟》开发的插件化自动驾驶辅…

作者头像 李华