news 2026/4/16 10:47:20

设计模式篇2——观察者模式:以直播间送礼系统举例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式篇2——观察者模式:以直播间送礼系统举例

在软件开发中,我们经常遇到这样的场景:一个动作发生后,需要同时触发一系列后续操作

如果你把这些操作全部写死在一个方法里,代码就会变成一团乱麻(所谓的“面条代码”),牵一发而动全身。今天,我们通过一个生动的直播间送礼案例,来聊聊如何用观察者模式优雅地解决这个问题。


1. 场景引入:不仅是送礼那么简单

假设你正在开发一个直播 App 的核心功能——送礼。 当用户送出一个“火箭”时,后台不仅仅是扣钱那么简单,通常还需要触发以下一堆子业务:

  1. 粉丝团系统:给用户增加粉丝团经验值。

  2. 抽奖系统:判断这次送礼是否触发了抽奖资格。

  3. PK系统:如果主播正在打 PK,需要给 PK 条增加分数。

  4. 特效系统:在公屏上播放炫酷动画。

[问题] 糟糕的实现方式(紧耦合)

如果不使用设计模式,你的GiftService代码很可能是这样的:

Java代码实现:

public void sendGift(User user, Gift gift) { // 1. 核心业务:扣费 walletService.deduct(user, gift.getPrice()); // 2. 杂七杂八的子业务(硬编码在这里) fanClubService.addExp(user, 10); // 耦合了粉丝团 lotteryService.check(user); // 耦合了抽奖 pkService.addScore(user, gift.getScore()); // 耦合了PK // 如果明天产品经理说要加个“成就系统”,你还得来改这行代码! }

痛点很明显:

  • 违反开闭原则:每次增加或删除子功能,都要修改sendGift核心代码。

  • 维护困难GiftService变得臃肿不堪,且依赖了太多它不该关心的服务。


2. 破局之道:观察者模式

观察者模式 (Observer Pattern)属于行为型设计模式。

通俗定义:它定义了一种一对多的依赖关系。当一个对象(主题)的状态发生改变时,所有依赖于它的对象(观察者)都会得到通知并自动更新。

映射到直播间场景

我们可以利用观察者模式,将“送礼”看作是一个信号,其他系统只需要监听这个信号即可。

  • Subject (主题/被观察者)->直播间送礼服务 (GiftService)

    • 职责:我是大喇叭。我只负责送礼,送完之后喊一声“有人送礼啦”,至于谁想知道,你们自己来我这里登记(注册)。

  • Observer (观察者)->粉丝团、抽奖、PK系统

    • 职责:我是听众。我订阅了送礼事件,一旦听到喇叭喊,我就赶紧干我自己的活。


3. 代码实战:解耦的艺术

让我们重构一下上面的代码。

第一步:定义观察者接口 (Observer)

所有想监听送礼事件的子系统,都必须遵守这个标准。

Java代码实现:

// 观察者接口 public interface GiftObserver { void onGiftSent(User user, Gift gift); }

第二步:实现具体的观察者 (ConcreteObserver)

各个子系统实现接口,编写自己的逻辑。

Java代码实现:

// 粉丝团观察者 public class FanClubObserver implements GiftObserver { @Override public void onGiftSent(User user, Gift gift) { System.out.println("粉丝团:增加经验值 +10"); } } // PK系统观察者 public class PkObserver implements GiftObserver { @Override public void onGiftSent(User user, Gift gift) { System.out.println("PK系统:PK条增加分数 " + gift.getScore()); } }

第三步:改造送礼服务 (Subject)

GiftService不再依赖具体的子系统,而是维护一个观察者列表。

Java代码实现:

public class GiftSubject { // 1. 维护一个观察者列表(花名册) private List<GiftObserver> observers = new ArrayList<>(); // 2. 注册方法(订阅) public void attach(GiftObserver observer) { observers.add(observer); } // 3. 移除方法(取消订阅) public void detach(GiftObserver observer) { observers.remove(observer); } // 4. 通知方法(广播) public void notifyObservers(User user, Gift gift) { for (GiftObserver observer : observers) { observer.onGiftSent(user, gift); } } // 核心业务逻辑 public void sendGift(User user, Gift gift) { // 核心逻辑:扣费 System.out.println("钱包:扣除余额 " + gift.getPrice()); // 关键点:只负责通知,不关心具体是谁在听! notifyObservers(user, gift); } }

4. 深度解析:优缺点与注意事项

优点:为什么我们要这么做?

  1. 极度解耦GiftService甚至不知道PKObserver的存在。两者只依赖于抽象接口。

  2. 扩展性强:双十一活动来了,需要送礼掉落碎片?只需新建一个ActivityObserver并注册进去,核心代码一行都不用改

  3. 符合开闭原则:对扩展开放,对修改关闭。

缺点:你需要警惕的坑

  1. 同步阻塞问题: 在 Java 的标准实现中,notifyObservers通常是顺序执行的(同步)。

    • 如果FanClubObserver卡顿了 5 秒,后面的PkObserver就得等 5 秒,用户的界面也会卡住。

    • 解决方案:对于非关键业务(如发通知、加经验),建议采用异步处理(放入线程池或消息队列)。

  2. 调试困难: 由于逻辑是分散的,不像面条代码那样一眼能看完,调试时可能需要在一个个观察者之间跳跃,流程比较隐晦。


5. 进阶:Spring 中的观察者模式

在实际的 Java 开发(特别是 Spring Boot)中,我们通常不需要自己手动写 Subject 和 Observer 接口,Spring 已经为我们封装好了事件发布-监听机制,这正是观察者模式的成熟落地。

  • 定义事件:继承ApplicationEvent(比如GiftSentEvent)。

  • 发布者 (Subject):使用ApplicationEventPublisher.publishEvent()

  • 监听者 (Observer):在方法上添加@EventListener注解。

这种方式比手动写 List 维护更加优雅,且天然支持解耦。


总结

观察者模式就像是生活中的订阅报纸。报社(Subject)只管印报纸并分发,它不知道也不关心是张三还是李四在读报纸。

当你发现系统中有**“牵一发而动全身”“一对多联动”**的业务场景时,请果断使用观察者模式。它能让你的核心逻辑保持纯净,让复杂的业务链路变得井井有条。

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

基于容器化的边缘计算网关应用部署实践:Python+MQTT

摘要&#xff1a; 传统的嵌入式开发面临交叉编译复杂、环境依赖难以管理等难题。利用容器化技术&#xff0c;我们可以将云原生的开发体验带入边缘侧。本文将以鲁邦通EG3110为硬件平台&#xff0c;演示如何构建一个Python数据处理容器&#xff0c;并通过MQTT与内置的 E2C Factor…

作者头像 李华
网站建设 2026/4/13 15:04:43

强烈安利继续教育TOP10AI论文平台:写论文不再难

强烈安利继续教育TOP10AI论文平台&#xff1a;写论文不再难 2026年继续教育AI论文平台测评&#xff1a;为何需要这份权威榜单 随着人工智能技术的快速发展&#xff0c;AI写作工具在学术领域的应用日益广泛。对于继续教育群体而言&#xff0c;撰写高质量论文不仅是学习成果的体现…

作者头像 李华
网站建设 2026/4/14 13:20:12

INVICTA BLz05-2/4 底座安装式电动振动电机

INVICTA BLz05-2/4底座安装式电动振动电机&#xff0c;作为BLz系列轻中型主力机型&#xff0c;传承英国品牌75年工业振动技术积淀&#xff0c;专为中小型散料处理场景打造高效灵活的激振动力解决方案。产品采用轻量化高强度底座设计&#xff0c;刚性固定结构紧凑可靠&#xff0…

作者头像 李华
网站建设 2026/4/13 9:30:31

XRay几何标定论文(5)阅读:Automated Flaw Detection in Aluminum Castings

是的&#xff0c;这篇论文详细介绍了X射线成像系统的几何校正&#xff08;标定&#xff09;方法&#xff0c;主要在第II章几何模型和附录A中详细说明。以下是校正方法的总结&#xff1a; 一、为什么要进行几何校正&#xff1f; X射线成像系统存在多种畸变&#xff1a; 图像增强…

作者头像 李华
网站建设 2026/4/16 10:21:23

【LLM大模型教程】RAG 修炼手册|一文讲透 RAG 背后的技术

我们已经介绍过 RAG 对于解决大模型幻觉问题的不可或缺性&#xff0c;也回顾了如何借助向量数据库提升 RAG 实战效果。 今天我们继续剖析 RAG&#xff0c;将为大家详细介绍 RAG 背后的例如 Embedding、Transformer、BERT、LLM 等技术的发展历程和基本原理&#xff0c;以及它们是…

作者头像 李华