mcpField
G
gof-observer

gof-observer

github.com/yonatankarp开发143 次安装23 周前更新
代码仓库

关于 gof-observer

介绍主体状态变化时通知多个依赖者的 Observer 模式。帮助开发者设计进程内更新机制,并权衡推送与拉取通知及常见实现陷阱。

主要功能

  1. 01主体与观察者角色
  2. 02注册与注销生命周期
  3. 03推送和拉取通知方式
  4. 04何时改用其他方案的指导
  5. 05Observer 常见陷阱

适用场景

  1. 01让多个视图与状态保持同步
  2. 02事件发生时通知订阅者
  3. 03解耦发布者与其依赖者

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yonatankarp/software-design-skills --skill gof-observer

安装后在 Claude Code 中输入/gof-observer确认已加载。

详细介绍

单行摘要

定义一种一对多依赖关系:当一个对象(主题)改变状态时,它的所有依赖对象(观察者)都会自动收到通知,而主题无需知道它们的具体类型。

何时使用此技能

  • 一个对象持有规范状态,而其他多个对象需要与之保持同步(数据 → 多个视图、模型 → 多个监听器)。
  • 事件式耦合:“当 X 发生时,执行这 N 项操作,而且操作列表会随时间增长。”
  • 将发布者与一组订阅者解耦,使发布者无需知道这些订阅者。

何时不使用此技能

  • 只有一个下游使用者——直接调用更简单。
  • “通知”必须同步执行,并阻塞主题,直到订阅者完成操作——观察者的典型实现采用推送方式,并假定订阅者彼此独立。
  • 你需要事件溯源、重放或持久化——这需要真正的事件总线/消息代理,而不是进程内的观察者模式。

核心内容

主题只知道 Observer 接口上的 notify() 方法。具体观察者通过 attach() / detach() 注册和注销。主题状态改变时,会遍历观察者列表,并对每个观察者调用 notify()。

推送与拉取:

  • 推送——主题将变更数据传入 notify(data)。简单直接;主题需要知道观察者想要什么。
  • 拉取——主题传入自身;观察者再查询所需数据。耦合更松;观察者只拉取所需内容。

大多数现代框架(RxJava、Kotlin Flow、EventBus 库、JavaFX 绑定,甚至 DOM 事件监听器)都实现了观察者模式的变体。

决策启发

  • 如果观察者关注相同的数据,推送即可;如果它们关注主题状态的不同子集,拉取更合适。
  • 保持观察者接口精简(一个方法)——臃肿的观察者接口会增加维护负担。
  • 对于超过少数几个订阅者,或涉及跨进程耦合的场景,应使用真正的事件总线(Kafka、RabbitMQ、Spring ApplicationEventPublisher),而不是手动实现观察者模式。

反模式

  • 观察者未注销会导致内存泄漏(主题会让它们一直存活)——应明确注销,并为此编写测试。
  • 观察者在 notify() 期间修改主题——会导致重入错误和观察者列表失效。
  • 依赖顺序的观察者——观察者模式保证通知,但不保证顺序;若顺序重要,应使用其他模式。

另请参阅

  • gof-command — 当“通知”需要排队、可撤销或参数化时。
  • gof-kotlin-idioms — 在 Kotlin 中,Flow、SharedFlow 和 StateFlow 是一等的观察者式原语;通常没必要自行实现观察者模式。

参考资料

  • Head First Design Patterns(第 2 版),第 2 章(“让对象知情:观察者模式”)——以气象监测站为例介绍此模式的经典章节。

评论

支持 Markdown