观察者模式讲解

张开发
2026/4/18 2:02:12 15 分钟阅读

分享文章

观察者模式讲解
观察者模式是行为型设计模式也叫发布 - 订阅模式Publish-Subscribe核心一句话总结建立「一对多」的依赖关系一个对象被观察者 / 主题的状态发生变化时所有依赖它的对象观察者都会收到自动通知并更新。一、它到底解决什么问题不使用观察者模式的痛点假设你做一个天气监测系统天气温度变了 → 要手动通知手机、电视、平板、车载设备代码里要写一堆phone.update()、tv.update()、pad.update()新增一个设备手表就要改原有代码 →严重耦合、违反开闭原则状态同步混乱容易漏通知、错通知使用观察者模式的效果天气被观察者只管自己更新状态所有设备观察者主动订阅天气天气一变 →自动广播通知所有订阅者新增设备只需要加一个观察者不用改原有代码二、观察者模式标准结构4 大核心角色观察者模式固定分为4 个角色缺一不可角色英文名作用抽象主题抽象被观察者Subject定义注册、移除、通知观察者的接口维护观察者列表具体主题具体被观察者ConcreteSubject实现抽象主题存储自身状态状态变化时调用notify()通知所有观察者抽象观察者Observer定义接收通知、更新数据的接口update()具体观察者ConcreteObserver实现抽象观察者收到通知后执行业务逻辑更新、展示、处理三、核心工作流程极简步骤观察者向被观察者注册订阅被观察者保存所有注册的观察者到列表被观察者状态发生变化被观察者调用notify()遍历列表通知所有观察者观察者执行update()完成自身更新五、C 完整代码实现逐行解析以气象站通知多个设备为案例代码可直接运行、注释详细#include iostream #include vector #include string using namespace std; // 前置声明观察者类 class Observer; // // 1. 抽象主题抽象被观察者核心接口定义 // class Subject { protected: // 观察者列表存储所有订阅的观察者 vectorObserver* observerList; public: // 注册观察者订阅 virtual void attach(Observer* observer) 0; // 移除观察者取消订阅 virtual void detach(Observer* observer) 0; // 通知所有观察者核心方法 virtual void notify() 0; virtual ~Subject() default; }; // // 2. 抽象观察者接收通知的接口 // class Observer { public: // 收到通知后执行更新参数是被观察者传递的新状态 virtual void update(const string weatherInfo) 0; virtual ~Observer() default; }; // // 3. 具体主题气象站真正的被观察者 // class WeatherStation : public Subject { private: // 被观察者的核心状态天气信息 string weather; public: // 实现注册观察者 void attach(Observer* observer) override { observerList.push_back(observer); cout 一个设备已订阅气象站 endl; } // 实现移除观察者 void detach(Observer* observer) override { for (auto it observerList.begin(); it ! observerList.end(); it) { if (*it observer) { observerList.erase(it); cout 一个设备已取消订阅 endl; break; } } } // 核心通知所有观察者 void notify() override { cout \n 气象站天气更新开始通知所有设备 endl; for (Observer* obs : observerList) { // 调用观察者的update方法传递最新天气 obs-update(weather); } } // 业务方法设置天气状态改变 void setWeather(const string newWeather) { this-weather newWeather; cout \n气象站更新天气 newWeather endl; // 状态改变自动通知 notify(); } }; // // 4. 具体观察者手机设备 // class PhoneObserver : public Observer { public: void update(const string weatherInfo) override { cout [手机设备] 收到最新天气 weatherInfo endl; } }; // // 5. 具体观察者电视设备 // class TVObserver : public Observer { public: void update(const string weatherInfo) override { cout [电视设备] 收到最新天气 weatherInfo endl; } }; // // 6. 具体观察者智能手表设备 // class WatchObserver : public Observer { public: void update(const string weatherInfo) override { cout [智能手表] 收到最新天气 weatherInfo endl; } }; // // 客户端测试代码 // int main() { // 1. 创建被观察者气象站 WeatherStation* station new WeatherStation(); // 2. 创建观察者多个设备 Observer* phone new PhoneObserver(); Observer* tv new TVObserver(); Observer* watch new WatchObserver(); // 3. 设备订阅气象站注册观察者 station-attach(phone); station-attach(tv); station-attach(watch); // 4. 气象站改变天气状态变化 → 自动通知 station-setWeather(晴天25℃微风); // 5. 手表取消订阅 station-detach(watch); // 6. 气象站再次更新天气 station-setWeather(小雨18℃降温); // 释放内存 delete watch; delete tv; delete phone; delete station; return 0; }运行结果plaintext一个设备已订阅气象站 一个设备已订阅气象站 一个设备已订阅气象站 气象站更新天气晴天25℃微风 气象站天气更新开始通知所有设备 [手机设备] 收到最新天气晴天25℃微风 [电视设备] 收到最新天气晴天25℃微风 [智能手表] 收到最新天气晴天25℃微风 一个设备已取消订阅 气象站更新天气小雨18℃降温 气象站天气更新开始通知所有设备 [手机设备] 收到最新天气小雨18℃降温 [电视设备] 收到最新天气小雨18℃降温六、观察者模式优缺点优点彻底解耦被观察者只依赖抽象观察者观察者只依赖抽象主题双方互不关心具体实现符合开闭原则新增观察者设备无需修改被观察者代码直接实现 Observer 接口即可广播式通知一次状态改变自动通知所有订阅者不用手动挨个调用动态订阅 / 取消运行时可随时注册、移除观察者灵活性极高缺点观察者过多时通知效率低同步通知会阻塞需异步优化可能出现循环依赖观察者通知被观察者被观察者又通知观察者 → 死循环通知顺序不可控默认按注册顺序通知无法指定优先级调试难度增加状态变化链式传递问题追踪复杂八、观察者模式 vs 发布 - 订阅模式易混点日常开发中常混用但严格区分观察者模式只有被观察者 ↔ 观察者直接通信耦合度稍高发布 - 订阅模式多一个中间代理Broker / 事件总线发布者和订阅者完全零耦合比如RabbitMQ 是发布 - 订阅有 Broker原生观察者模式是直接通知无中间层九、终极总结核心一对多依赖状态自动广播通知角色抽象主题 具体主题 抽象观察者 具体观察者流程订阅 → 状态变 → 通知 → 更新核心价值解耦、开闭原则、动态扩展一句话记忆你关注我我变了就告诉你不用我挨个找你。

更多文章