设计模式:观察者模式 - 实战

article/2025/8/22 14:32:59

一、观察者模式场景

1.1 什么是观察者模式?
观察者模式(Observer Pattern)观察者模式是一种行为型设计模式,用于定义一种一对多的依赖关系,当对象的状态发生变化时,所有依赖于它的对象都会自动收到通知并更新。

核心思想观察者模式实现了对象之间的解耦:被观察者(Subject)专注于自身状态的管理,而观察者(Observer)专注于对状态变化的响应,二者通过通知机制进行交互

1.2 传统开发模式的三大死穴

强耦合陷阱:订单状态变更需要手动调用10+通知服务(邮件/SMS/物流…)

扩展噩梦:新增通知渠道必须修改核心业务代码(违反OCP原则)

性能瓶颈:同步调用链导致接口响应时间突破2秒红线

1.3 观察者模式的破局之道
事件驱动架构:业务逻辑与事件处理物理隔离

动态扩展能力:新增观察者零侵入核心系统

异步削峰:实测QPS提升300%(订单支付场景)

1.4 优点

解耦:被观察者和观察者之间的耦合度低,便于扩展。

动态联动:可以动态添加、移除观察者,灵活性强。

符合开闭原则:被观察者的状态变化通知机制对扩展开放,对修改关闭。

1.5 缺点

性能问题:观察者过多时,通知机制可能导致性能开销。

复杂性增加:过多的观察者与被观察者关系可能增加系统的复杂性。

可能产生循环依赖:若观察者与被观察者相互依赖,可能导致循环调用。

1.6 应用场景

事件驱动模型:如 UI 事件监听器(按钮点击等)。

发布-订阅机制:消息队列、事件总线等。

状态同步:某一对象的状态变化需要通知多个依赖对象时。

二、技术方案设计

2.1 架构演进对比
在这里插入图片描述

2.2 核心组件设计

[事件源] --发布--> [EventBus] --通知--> [观察者集群]↑                    ↖[事件对象]               [线程池分发]

三、Java原生实现

3.1 基于JDK的经典实现

// 支付成功事件定义
public class PaymentSuccessEvent extends EventObject {private final String orderId;private final BigDecimal amount;public PaymentSuccessEvent(Object source, String orderId, BigDecimal amount) {super(source);this.orderId = orderId;this.amount = amount;}
}// 支付服务(事件源)
public class PaymentService {private final List<EventListener> listeners = new CopyOnWriteArrayList<>();public void addListener(EventListener listener) {listeners.add(listener);}public void pay(String orderId, BigDecimal amount) {// 支付核心逻辑...notifyListeners(new PaymentSuccessEvent(this, orderId, amount));}private void notifyListeners(PaymentSuccessEvent event) {listeners.forEach(listener -> listener.onEvent(event));}
}// 邮件通知观察者
public class EmailNotifier implements EventListener {@Overridepublic void onEvent(EventObject event) {if (event instanceof PaymentSuccessEvent) {PaymentSuccessEvent e = (PaymentSuccessEvent) event;sendEmail(e.getOrderId(), e.getAmount());}}
}

3.2 Java9+改进方案

// 使用Flow API实现响应式流
public class PaymentPublisher implements Flow.Publisher<PaymentEvent> {private final Executor executor = ForkJoinPool.commonPool();private final List<Flow.Subscriber<? super PaymentEvent>> subscribers = new CopyOnWriteArrayList<>();@Overridepublic void subscribe(Flow.Subscriber<? super PaymentEvent> subscriber) {subscribers.add(subscriber);subscriber.onSubscribe(new PaymentSubscription(subscriber));}private class PaymentSubscription implements Flow.Subscription {private final Flow.Subscriber<? super PaymentEvent> subscriber;PaymentSubscription(Flow.Subscriber<? super PaymentEvent> subscriber) {this.subscriber = subscriber;}@Overridepublic void request(long n) {// 背压处理}@Overridepublic void cancel() {subscribers.remove(subscriber);}}
}

四、Spring生态进阶实现

4.1 基于ApplicationEvent

// 配置中心变更事件
public class ConfigUpdateEvent extends ApplicationEvent {private final String configKey;private final String newValue;public ConfigUpdateEvent(Object source, String configKey, String newValue) {super(source);this.configKey = configKey;this.newValue = newValue;}
}// 动态配置观察者
@Component
public class ConfigRefreshListener {@EventListener@Asyncpublic void handleConfigUpdate(ConfigUpdateEvent event) {refreshConfigCache(event.getConfigKey(), event.getNewValue());notifyAllServers(event);}
}// 事件发布
@Service
public class ConfigService {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void updateConfig(String key, String value) {// 更新数据库eventPublisher.publishEvent(new ConfigUpdateEvent(this, key, value));}
}

4.2 注解驱动增强

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BusinessEventListener {String[] keys() default {};EventMode mode() default EventMode.ASYNC;
}// AOP切面处理
@Aspect
@Component
public class EventListenerAspect {@Around("@annotation(listener)")public Object processEvent(ProceedingJoinPoint pjp, BusinessEventListener listener) {EventObject event = (EventObject) pjp.getArgs()[0];if (shouldHandle(event, listener.keys())) {return switch (listener.mode()) {case ASYNC -> CompletableFuture.runAsync(() -> proceed(pjp));case TRANSACTIONAL -> executeInTransaction(pjp);default -> proceed(pjp);};}return null;}
}

五、生产级优化方案

5.1 性能优化策略
在这里插入图片描述

5.2 可靠性保障

// 事件持久化方案
public class PersistentEventBus {private final EventStoreRepository eventStore;@Transactional(propagation = Propagation.REQUIRES_NEW)public void publishWithPersistence(DomainEvent event) {eventStore.save(event);realPublish(event);}// 定时补偿任务@Scheduled(fixedRate = 60000)public void retryFailedEvents() {eventStore.findFailedEvents().forEach(event -> {try {realPublish(event);event.markAsSent();} catch (Exception e) {event.recordRetry();}});}
}

六、经典应用场景

6.1 电商订单系统

支付成功事件 → 库存扣减/物流触发/积分发放使用「发布-确认-补偿」机制保证最终一致性

6.2 微服务配置中心

配置变更事件 → 所有服务实例动态刷新结合Spring Cloud Bus实现集群通知

6.3 物联网数据采集

设备状态事件 → 实时监控/预警分析/大屏展示采用MQTT协议实现百万级设备连接

七、避坑指南

7.1 常见问题排查
内存泄漏:

检查观察者是否及时取消注册

使用WeakReference包装监听器

事件丢失:

增加本地事件持久化层

实现至少一次投递语义

循环触发:

在事件对象中添加traceId

设置最大传播深度阈值

7.2 生产注意事项
事件版本控制:使用Avro Schema管理事件格式

监控埋点:统计事件处理耗时/成功率

熔断降级:Hystrix隔离异常观察者


http://www.hkcw.cn/article/TrIetqxcaW.shtml

相关文章

首发!PPIO派欧云上线DeepSeek-R1-0528

今天凌晨&#xff0c;“小版本试升级”的 DeepSeek-R1-0528 在 Hugging Face 正式开源。 经 PPIO派欧云工程师测试&#xff0c;这个所谓的“小版本”更新在代码领域大幅增强&#xff0c;凭借简单朴素的提示词就能生成小游戏、图片、精美的网页&#xff0c;生成效果可媲美 Claud…

国务院任免21名干部 涉及多个重要职位调整

国务院任免21名干部 涉及多个重要职位调整!据人社部网站5月29日消息,国务院任免了21名国家工作人员。郭彩云(女)被任命为审计署副审计长,王军为海关总署副署长,蔡自力为国家税务总局副局长,邹晓东为国务院参事室主任,赵世通为国务院台湾事务办公室副主任,李长喜为国家…

【STM32开发板】电源设计(电压基准、滤波电容)

一、基准电压源 基准电压源是一种能提供稳定、精确、不随温度、负载、电源电压变化而波动的电压源。它广泛应用于电子电路中&#xff0c;尤其是在需要高精度和稳定性的场合&#xff0c;如模数转换&#xff08;ADC&#xff09;、 数模转换&#xff08;DAC&#xff09;、稳压电路…

男大学生正在批量减少:教育竞争中的性别差异显现

男大学生正在批量减少:教育竞争中的性别差异显现!毕业季即将来临,校园里随处可见穿着学位服的毕业生在草坪上拍照。她们对着镜头比出剪刀手,或是抱着鲜花和室友笑成一团。图书馆前台阶上,三五成群的学生捧着论文材料匆匆走过,教室里答辩结束的学生红着眼眶与导师拥抱。仔…

K8S StatefulSet 快速开始

其实这篇文章的梗概已经写了很久了&#xff0c;中间我小孩出生了&#xff0c;从此人间多了一份牵挂。抽出一些时间去办理新生儿相关手续。初为人父确实艰辛&#xff0c;就像学技术一样&#xff0c;都需要有极大的耐心&#xff0c;付出很多的时间。 一、引子 1.1、独立的存储 …

【笔记】suna部署之获取 Daytona API key 及 Daytona Sandbox 设置

#工作记录 Daytona 注册 Daytona 账户 访问Daytona 官方网站。点击注册按钮&#xff0c;按照提示填写相关信息完成注册。 获取 Daytona API 密钥 登录 Daytona 账户。进入账户设置页面&#xff0c;查找生成 API 密钥的选项&#xff0c;生成并复制 API 密钥&#xff0c;用于 S…

昇腾首发支持,阶跃星辰 “改图大师” Step1X-Edit开源并上线魔乐社区

4月27日&#xff0c;阶跃星辰正式发布并开源图像编辑大模型 Step1X-Edit &#xff0c;性能达到开源 SOTA 。该模型总参数量为19B (7B MLLM 12B DiT)&#xff0c;具备语义精准解析、身份一致性保持、高精度区域级控制三项关键能力&#xff1b;支持11类高频图像编辑任务类型&…

int和Integer的区别

Java是面向对象的语言&#xff0c;一切操作都以对象为基础&#xff0c;像集合里面也只支持存储Object类型数据&#xff0c;普通类型无法通过集合存储&#xff0c; 在Java中&#xff0c;int和Integer是两种不同的类型&#xff0c;它们有以下主要区别&#xff1a; 一、类型分类…

Oracle/openGauss中,DATE/TIMESTAMP与数字日期/字符日期比较

ORACLE 运行环境 openGauss 运行环境 0、前置知识 ORACLE&#xff1a;DUMP()函数用于返回指定表达式的数据类型、字节长度及内部存储表示的详细信息 SELECT DUMP(123) FROM DUAL; -- Typ2 Len3: 194,2,24 SELECT DUMP(123) FROM DUAL;-- Typ96 Len3: 49,50,51 -- ASCII值&am…

应用于公路路面破损状况检测的视觉系统

随着公路交通的日益发展&#xff0c;公路交通也是经济命脉&#xff0c;路面病害检测直接关系到交通安全&#xff0c;公路路面检测是养护管理的核心环节&#xff0c;及时识别裂缝、坑槽、车辙等病害&#xff0c;避免因路面损坏引发交通事故。 公路路面基病害检测系统是基于数字图…

ZeroSearch: 无需搜索即可激发LLM的搜索能力

论文地址&#xff1a;https://arxiv.org/abs/2505.04588v2 摘要 有效的的信息搜索对于增强大型语言模型 (LLM) 的推理和生成能力至关重要。 最近的研究探索了使用强化学习 (RL) 通过与现实世界环境中的实时搜索引擎交互来提高 LLM 的搜索能力。 虽然这些方法显示出可喜的结果&…

Linux实操篇-进程管理

目录 传送门前言一、进程管理概念二、进程管理实战1. **查看进程**ps 命令top 命令htop 命令 2. **进程的启动和终止**启动进程停止进程使用 pkill 或 killall 3. **进程优先级管理**nice 和 renice 命令top 中调整进程优先级 4. **进程的查看与控制**pgrep 命令pstree 命令str…

DAY 14 SHAP库的绘制

上面这个图就是一个比较直观的解释。机器学习模型一般都是一个黑盒。比如某个模型要进行一些预测任务&#xff0c;首先对模型输入一些已知条件&#xff08;Age65,SexF,BP180,BMI40&#xff09;&#xff0c;然后模型根据输入进行训练&#xff0c;最终训练完的模型可以对该条件输…

如何避免客户频繁更换对接人

避免客户频繁更换对接人的关键措施包括建立稳定的客户关系、提高客户对接人的专业素养、建立高效的沟通机制、增强客户满意度等。其中&#xff0c;建立稳定的客户关系是避免客户频繁更换对接人的核心&#xff0c;只有当客户信任你的对接人并认可其专业性&#xff0c;才会持续稳…

5.29打卡

浙大疏锦行 DAY 38 Dataset和Dataloader类 知识点回顾&#xff1a; 1. Dataset类的__getitem__和__len__方法&#xff08;本质是python的特殊方法&#xff09; 2. Dataloader类 3. minist手写数据集的了解 作业&#xff1a;了解下cifar数据集&#xff0c;尝试获取其中一张图…

【芯片设计中的交通网络革命:Crossbar与NoC架构的博弈C架构的博弈】

在芯片设计领域&#xff0c;总线架构如同城市交通网&#xff0c;决定了数据流的通行效率。随着AI芯片、车载芯片等复杂场景的爆发式增长&#xff0c;传统总线架构正面临前所未有的挑战。本文将深入解析两大主流互连架构——Crossbar与NoC的优劣&#xff0c;揭示芯片"交通网…

官方将调查小车坠桥事故车道设计 四车道突收窄引关注

官方将调查小车坠桥事故车道设计 四车道突收窄引关注!近日,广东东莞环莞快速路虎门段发生了一起严重的交通事故。5月19日,一名网友称其侄儿驾车经过该路段时,由于四车道突然收窄为三车道,车辆失控从高架冲出路面,造成车上5人伤亡。5月29日,广东虎门镇“519”事故工作专班…

中国航天史上最长任务开启 谁来接力“天问”?

5月29日,天问二号任务发射圆满成功,我国开启小行星探测与采样返回之旅。天问二号任务设计周期10年左右,如此长的任务周期,是否拉开了太空探索新的序幕?此次任务的“双目标探测”探什么?有多难?天问二号的十年之约对于我们的航天人才储备意味着什么?中国航天史上最长太空…

雪龙2号将面向公众开放:极地科考成果展示

5月28日,“雪龙2”号极地科考破冰船抵达海南海口,标志着中国第41次南极考察队顺利完成全部考察任务。“雪龙2”号计划近期举办公众开放日活动,这是该船首次抵琼并面向公众开放。“雪龙2”号于2024年11月1日从广州出发,历时208天,总航程超过4万海里。此次考察的最大亮点在于…

Kubernetes 中部署 kube-state-metrics 及 Prometheus 监控配置实战

文章目录 Kubernetes 中部署 kube-state-metrics 及 Prometheus 监控配置实战环境准备创建监控命名空间准备配置文件创建 ServiceAccount配置 RBAC 权限部署 kube-state-metrics部署node_exporter(可选)验证服务账号 TokenPrometheus 配置示例小结验证增加Grafana面板增加prome…