1. 什么是观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式,用于在对象之间建立一对多的依赖关系。当一个对象(称为主题或被观察者)的状态发生变化时,所有依赖它的对象(称为观察者)都会自动收到通知并更新自身状态。
这种模式的核心思想是:主题不直接调用观察者的方法,而是通过发布通知的方式,让观察者自行响应变化。这样主题和观察者之间就实现了松耦合,双方可以独立扩展和复用。
2. 模式结构
观察者模式主要包含以下四个角色:
- Subject(主题):维护观察者列表,提供注册、注销和通知方法。
- ConcreteSubject(具体主题):实现主题接口,状态变化时触发通知。
- Observer(观察者):定义接收通知的更新接口。
- ConcreteObserver(具体观察者):实现更新接口,响应主题状态变化。
3. 代码示例
下面以 C/C++ 为例,演示观察者模式的基本实现。
#include <iostream> #include <list> #include <string> // 观察者接口 class Observer { public: virtual ~Observer() {} virtual void update(const std::string& message) = 0; }; // 主题接口 class Subject { public: virtual ~Subject() {} virtual void attach(Observer* observer) = 0; virtual void detach(Observer* observer) = 0; virtual void notifyObservers() = 0; }; // 具体主题 class NewsPublisher : public Subject { private: std::list<Observer*> observers; std::string news; public: void attach(Observer* observer) override { observers.push_back(observer); } void detach(Observer* observer) override { observers.remove(observer); } void notifyObservers() override { for (Observer* observer : observers) { observer->update(news); } } void publishNews(const std::string& news) { this->news = news; notifyObservers(); } }; // 具体观察者 class EmailSubscriber : public Observer { private: std::string name; public: EmailSubscriber(const std::string& name) : name(name) {} void update(const std::string& message) override { std::cout << name << " 收到新闻:" << message << std::endl; } }; // 客户端测试 int main() { NewsPublisher publisher; EmailSubscriber alice("Alice"); EmailSubscriber bob("Bob"); publisher.attach(&alice); publisher.attach(&bob); publisher.publishNews("观察者模式发布了一条新消息"); return 0; }4. 适用场景
观察者模式在以下场景中非常实用:
- 事件监听系统:如 GUI 按钮点击、鼠标移动等事件分发。
- 消息推送:如订阅号推送、邮件通知、App 消息提醒。
- 数据同步:多个视图需要同步显示同一份数据变化。
- 分布式系统:如消息队列中的发布-订阅模型。
5. 优缺点分析
优点:
- 主题和观察者之间松耦合,便于独立扩展。
- 支持广播通信,一个主题可同时通知多个观察者。
- 符合开闭原则,新增观察者无需修改主题代码。
缺点:
- 观察者过多时,通知效率可能下降。
- 观察者之间可能存在间接依赖,导致调试困难。
- 如果观察者更新逻辑复杂,可能引发性能问题。
6. 总结
观察者模式通过发布-订阅机制,让对象之间的依赖关系更加灵活和可维护。它在事件驱动架构、消息推送和数据同步等场景中应用广泛,是日常开发中非常实用的设计模式之一。