设计模式实战:观察者模式(Observer)

在很多系统中,你会遇到这样的需求:

  • 数据变化了,要通知多个模块
  • 一个事件发生,需要触发多个动作
  • 状态更新后,界面自动刷新

例如:

  • 订单状态变化 → 通知用户、更新库存、记录日志
  • 配置变更 → 通知多个服务刷新缓存
  • 前端数据变化 → 自动更新 UI

如果你这样写:

python 复制代码
def update():
    notify_user()
    update_stock()
    write_log()

问题很快就会出现:

  • 每增加一个功能,就要改原函数
  • 模块之间强耦合
  • 代码越来越难维护

这正是 观察者模式(Observer) 要解决的问题。


一、观察者模式解决什么问题?

一句话:

定义对象之间的一对多依赖关系,当一个对象状态发生变化时,所有依赖它的对象都会自动收到通知。

关键词:

  • 一对多
  • 事件通知
  • 解耦
  • 自动触发

二、核心角色

观察者模式通常包含两个核心角色:

1️⃣ Subject(被观察者)

  • 维护观察者列表
  • 状态变化时发出通知

2️⃣ Observer(观察者)

  • 接收通知
  • 执行对应逻辑

结构:

复制代码
Subject  --->  Observer1
         --->  Observer2
         --->  Observer3

三、一个典型场景:订单状态通知

假设订单状态发生变化,需要:

  • 通知用户
  • 更新库存
  • 写日志

四、Python 实现观察者模式

1️⃣ 定义观察者接口

python 复制代码
from abc import ABC, abstractmethod

class Observer(ABC):

    @abstractmethod
    def update(self, data):
        pass

2️⃣ 定义被观察者

python 复制代码
class Subject:

    def __init__(self):
        self._observers = []

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self, data):
        for observer in self._observers:
            observer.update(data)

3️⃣ 具体观察者

python 复制代码
class UserNotifier(Observer):

    def update(self, data):
        print("通知用户:", data)


class StockUpdater(Observer):

    def update(self, data):
        print("更新库存:", data)


class Logger(Observer):

    def update(self, data):
        print("记录日志:", data)

4️⃣ 使用方式

python 复制代码
subject = Subject()

subject.attach(UserNotifier())
subject.attach(StockUpdater())
subject.attach(Logger())

subject.notify("订单已支付")

输出:

复制代码
通知用户: 订单已支付
更新库存: 订单已支付
记录日志: 订单已支付

五、观察者模式的核心价值

观察者模式本质是:

发布-订阅机制(Publish-Subscribe)

它解决的是:

  • 模块之间强耦合
  • 扩展困难
  • 逻辑分散

改成观察者后:

  • 新增功能 → 新增观察者
  • 不需要修改原逻辑

六、Python 更简洁的实现(函数版)

在 Python 中,不一定要写类。

可以直接用函数:

python 复制代码
class Subject:

    def __init__(self):
        self._observers = []

    def subscribe(self, func):
        self._observers.append(func)

    def notify(self, data):
        for func in self._observers:
            func(data)

使用:

python 复制代码
def log(data):
    print("日志:", data)

def notify_user(data):
    print("用户通知:", data)

subject = Subject()
subject.subscribe(log)
subject.subscribe(notify_user)

subject.notify("订单完成")

更简洁、更 Pythonic。


七、观察者 vs 事件驱动

观察者模式其实就是:

轻量级事件系统

现实中的对应:

  • 前端事件监听(addEventListener)
  • Node.js EventEmitter
  • Django Signals
  • 消息队列(升级版)

八、观察者模式的常见问题

1️⃣ 通知顺序问题

观察者执行顺序可能影响结果。

解决:

  • 排序
  • 优先级机制

2️⃣ 循环依赖

观察者触发 Subject,再触发观察者 → 死循环。

需要:

  • 控制触发条件
  • 防止递归调用

3️⃣ 性能问题

观察者过多:

  • 通知耗时增加
  • 可能阻塞主流程

可以:

  • 异步处理
  • 消息队列

九、真实项目中的应用

非常常见:

1️⃣ 订单系统

状态变化 → 多个模块响应


2️⃣ 配置中心

配置更新 → 通知服务刷新


3️⃣ 前端框架

Vue / React:

  • 数据变化 → UI 自动更新

4️⃣ 日志/监控系统

事件触发 → 多个监控模块响应


十、观察者模式优缺点

✅ 优点

  • 解耦
  • 易扩展
  • 符合开闭原则
  • 支持事件驱动

❌ 缺点

  • 依赖关系不明显(调试困难)
  • 通知链条复杂
  • 可能影响性能

十一、什么时候使用观察者模式?

适合:

  • 一个对象变化 → 多个对象响应
  • 需要解耦模块
  • 事件驱动系统

不适合:

  • 简单调用关系
  • 不需要扩展

十二、一句话总结

观察者模式的本质是:
一处变化,多处响应。

换句话说:

不要在一个函数里写所有逻辑,把它们"订阅"出去。


相关推荐
萌>__<新2 小时前
AI聊天助手-测试报告
人工智能·python
Humbunklung2 小时前
WMO 天气代码(Code Table 4677)深度解析与应用报告
开发语言·数据库·python
weixin_449290012 小时前
uv打包Python为exe步骤
开发语言·python·uv
书到用时方恨少!2 小时前
Python threading 使用指南:并发编程的轻骑兵
python·多线程·thread·多任务
努力学习_小白2 小时前
数据增强——tensorflow
人工智能·python·tensorflow
m0_694845572 小时前
marimo搭建教程:替代Jupyter的交互式开发工具
服务器·ide·python·docker·jupyter·github
csdn2015_3 小时前
Set<String> 类型取第一条记录
开发语言·windows·python
csdn2015_3 小时前
List<String> 转换为Set<String>
windows·python·list
Chen--Xing3 小时前
Python -- 正则表达式
python·正则表达式·数据分析·数据脱敏·2025年能源网络安全大赛