关于 gof-observer
介绍主体状态变化时通知多个依赖者的 Observer 模式。帮助开发者设计进程内更新机制,并权衡推送与拉取通知及常见实现陷阱。
主要功能
- 01主体与观察者角色
- 02注册与注销生命周期
- 03推送和拉取通知方式
- 04何时改用其他方案的指导
- 05Observer 常见陷阱
适用场景
- 01让多个视图与状态保持同步
- 02事件发生时通知订阅者
- 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