三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系:当一个对象(称为“被观察者”或“Subject”)的状态发生改变时,所有依赖于它的对象(称为“观察者”或“Observers”)都会自动收到通知并更新。该模式解耦了被观察者与观察者,支持动态添加/移除观察者,广泛应用于事件驱动系统、GUI框架(如Java Swing、Android LiveData)、消息总线、发布-订阅系统等场景。

典型结构包括:

  • Subject(被观察者):维护观察者列表,提供注册(attach)、注销(detach)和通知(notify)方法;
  • Observer(观察者):定义更新接口(如update()),由具体观察者实现;
  • 具体被观察者(ConcreteSubject)与具体观察者(ConcreteObserver)实现各自逻辑。

优点:松耦合、可扩展性强、支持广播通信;
缺点:可能引发内存泄漏(若未及时注销)、通知顺序不可控、缺乏回调反馈机制(观察者无法向被观察者返回结果)。

fromabcimportABC,abstractmethodfromtypingimportList,AnyclassObserver(ABC):@abstractmethoddefupdate(self,data:Any)->None:passclassSubject(ABC):def__init__(self):self._observers:List[Observer]=[]defattach(self,observer:Observer)->None:ifobservernotinself._observers:self._observers.append(observer)defdetach(self,observer:Observer)->None:ifobserverinself._observers:self._observers.remove(observer)defnotify(self,data:Any)->None:forobserverinself._observers:observer.update(data)# 示例:天气站通知订阅者classWeatherStation(Subject):defset_temperature(self,temp:float)->None:print(f"天气站更新温度:{temp}°C")self.notify(temp)classPhoneDisplay(Observer):defupdate(self,data:float)->None:print(f"[手机端] 收到温度更新:{data}°C")classWebDisplay(Observer):defupdate(self,data:float)->None:print(f"[网页端] 收到温度更新:{data}°C")# 使用示例station=WeatherStation()phone=PhoneDisplay()web=WebDisplay()station.attach(phone)station.attach(web)station.set_temperature(25.6)# 输出两条通知

观察者模式(Observer)与发布-订阅模式(Pub/Sub)本质目标相似(解耦通知方与接收方),但核心区别在于通信耦合度与中介角色的存在与否,因此不属于严格意义上的同一类模式,而是演进关系:Pub/Sub 可视为观察者模式的松耦合变体或扩展。

核心区别对比

维度观察者模式(Observer)发布-订阅模式(Pub/Sub)
耦合方式被观察者(Subject)直接持有并调用观察者(Observer)引用 →存在直接引用耦合发布者(Publisher)与订阅者(Subscriber)均不互相持有引用,全部通过中间消息代理(Event Bus / Message Broker)通信 →完全解耦
注册机制观察者主动向被观察者注册(subject.attach(observer)订阅者向事件总线注册感兴趣的主题(topic),发布者也只面向总线发布,不感知谁订阅
消息传递通知是同步、即时的方法调用(observer.update()通常支持异步、缓冲、持久化、过滤、广播/单播等高级语义;消息可被暂存、重放、路由
生命周期管理被观察者需显式管理观察者列表(增删),易引发内存泄漏(如未detach)总线统一管理订阅关系,更易实现自动清理(如基于弱引用、超时注销)
典型实现Javajava.util.Observable(已弃用)、.NETIObservable<T>、前端EventTarget.addEventListenerRedis Pub/Sub、RabbitMQ、Vue 3 的mitt、RxJS 的Subject(增强版)、Node.js 的events.EventEmitter(轻量级近似)

🔍关键洞察

  • 观察者模式是对象层级的、同步的、内存内的通知机制;
  • Pub/Sub 是系统/服务层级的、常为异步的、可能跨进程/网络的消息范式,引入了中介(Broker)作为第一公民
    → 因此,Pub/Sub 是观察者模式在分布式、高内聚低耦合需求下的抽象升级,而非简单等价替换
# 简化对比示例:同一事件“用户登录成功”# ✅ Observer(紧耦合):user_service.attach(login_logger)# user_service 直接知道 login_loggeruser_service.attach(email_notifier)user_service.notify_login(user)# 同步调用两个对象方法# ✅ Pub/Sub(松耦合):event_bus.publish("user.login",{"user_id":123})# user_service 不知谁监听# login_logger 和 email_notifier 各自向 event_bus 订阅 "user.login"# event_bus 负责分发,二者互不可见

← 返回列表