C++实现设计模式--- 观察者模式 (Observer)

打印 上一主题 下一主题

主题 1022|帖子 1022|积分 3066

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
观察者模式 (Observer)

观察者模式 是一种举动型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,其依赖者(观察者)会收到关照并主动更新。

意图



  • 定义对象之间的一对多依赖关系。
  • 当一个对象状态发生厘革时,关照所有依赖于它的对象。

利用场景


  • 变乱驱动系统

    • 如 GUI 程序中的按钮点击变乱,按钮关照所有监听器。

  • 数据厘革关照

    • 数据模型的厘革需要关照多个视图更新。

  • 解耦对象之间的依赖

    • 被观察者与观察者通过接口交互,低落了耦合性。


参与者角色


  • 主题 (Subject)

    • 被观察者,维护观察者列表,并在状态发生厘革时关照所有观察者。

  • 观察者 (Observer)

    • 定义了一个接口,用于吸收关照并更新状态。

  • 具体主题 (ConcreteSubject)

    • 实现具体的主题逻辑,存储状态,并在状态改变时关照观察者。

  • 具体观察者 (ConcreteObserver)

    • 实现具体的观察者逻辑,吸收关照并更新状态。


示例代码

以下代码展示了观察者模式的实现,利用 C++ 的现代特性(如 std::function、std::vector、shared_ptr)。
  1. #include <iostream>
  2. #include <vector>
  3. #include <memory>
  4. #include <functional>
  5. #include <string>
  6. // 观察者接口
  7. class Observer {
  8. public:
  9.     virtual ~Observer() = default;
  10.     virtual void update(const std::string& message) = 0; // 接收通知
  11. };
  12. // 具体观察者:实现观察者接口
  13. class ConcreteObserver : public Observer {
  14. private:
  15.     std::string name; // 观察者名称,用于标识
  16. public:
  17.     explicit ConcreteObserver(const std::string& observerName) : name(observerName) {}
  18.     void update(const std::string& message) override {
  19.         std::cout << "观察者 [" << name << "] 收到通知: " << message << std::endl;
  20.     }
  21. };
  22. // 被观察者接口
  23. class Subject {
  24. public:
  25.     virtual ~Subject() = default;
  26.     virtual void attach(std::shared_ptr<Observer> observer) = 0; // 添加观察者
  27.     virtual void detach(std::shared_ptr<Observer> observer) = 0; // 移除观察者
  28.     virtual void notify() = 0;                                   // 通知观察者
  29. };
  30. // 具体被观察者:实现被观察者接口
  31. class ConcreteSubject : public Subject {
  32. private:
  33.     std::vector<std::shared_ptr<Observer>> observers; // 存储观察者的列表
  34.     std::string state;                                // 被观察者的状态
  35. public:
  36.     void attach(std::shared_ptr<Observer> observer) override {
  37.         observers.push_back(observer);
  38.     }
  39.     void detach(std::shared_ptr<Observer> observer) override {
  40.         observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
  41.     }
  42.     void setState(const std::string& newState) {
  43.         state = newState;
  44.         notify(); // 状态改变时通知所有观察者
  45.     }
  46.     void notify() override {
  47.         for (const auto& observer : observers) {
  48.             observer->update(state);
  49.         }
  50.     }
  51. };
  52. // 客户端代码
  53. int main() {
  54.     auto subject = std::make_shared<ConcreteSubject>();
  55.     // 创建多个观察者
  56.     auto observer1 = std::make_shared<ConcreteObserver>("Observer1");
  57.     auto observer2 = std::make_shared<ConcreteObserver>("Observer2");
  58.     auto observer3 = std::make_shared<ConcreteObserver>("Observer3");
  59.     // 观察者订阅被观察者
  60.     subject->attach(observer1);
  61.     subject->attach(observer2);
  62.     subject->attach(observer3);
  63.     // 修改被观察者的状态,通知观察者
  64.     std::cout << "修改状态为: 状态A" << std::endl;
  65.     subject->setState("状态A");
  66.     // 移除一个观察者
  67.     subject->detach(observer2);
  68.     std::cout << "修改状态为: 状态B" << std::endl;
  69.     subject->setState("状态B");
  70.     return 0;
  71. }
复制代码

代码剖析

1. 观察者接口 (Observer)



  • 定义了一个 update 方法,用于吸收关照:
  1. class Observer {
  2. public:
  3.     virtual ~Observer() = default;
  4.     virtual void update(const std::string& message) = 0; // 接收通知
  5. };
复制代码
2. 具体观察者 (ConcreteObserver)



  • 实现了 Observer 接口,并通过 update 方法更新状态:
  1. class ConcreteObserver : public Observer {
  2. private:
  3.     std::string name;
  4. public:
  5.     explicit ConcreteObserver(const std::string& observerName) : name(observerName) {}
  6.     void update(const std::string& message) override {
  7.         std::cout << "观察者 [" << name << "] 收到通知: " << message << std::endl;
  8.     }
  9. };
复制代码
3. 被观察者接口 (Subject)



  • 定义了添加、移除观察者的方法,以及关照观察者的 notify 方法:
  1. class Subject {
  2. public:
  3.     virtual ~Subject() = default;
  4.     virtual void attach(std::shared_ptr<Observer> observer) = 0;
  5.     virtual void detach(std::shared_ptr<Observer> observer) = 0;
  6.     virtual void notify() = 0;
  7. };
复制代码
4. 具体被观察者 (ConcreteSubject)



  • 存储观察者列表,并在状态改变时关照观察者:
  1. class ConcreteSubject : public Subject {
  2. private:
  3.     std::vector<std::shared_ptr<Observer>> observers;
  4.     std::string state;
  5. public:
  6.     void setState(const std::string& newState) {
  7.         state = newState;
  8.         notify(); // 状态改变时通知所有观察者
  9.     }
  10.     void notify() override {
  11.         for (const auto& observer : observers) {
  12.             observer->update(state);
  13.         }
  14.     }
  15. };
复制代码
5. 客户端



  • 客户端通过 attach 方法订阅观察者,并通过 setState 方法触发关照:
  1. auto subject = std::make_shared<ConcreteSubject>();
  2. auto observer1 = std::make_shared<ConcreteObserver>("Observer1");
  3. subject->attach(observer1);
  4. subject->setState("状态A");
复制代码

优缺点

优点


  • 解耦

    • 被观察者与观察者之间通过接口交互,低落了依赖性。

  • 扩展性强

    • 可以轻松增长新的观察者,而无需修改被观察者代码。

  • 动态关照

    • 可以在运行时动态添加或移除观察者。

缺点


  • 关照开销

    • 当观察者较多时,关照的开销可能较大。

  • 复杂性增长

    • 系统中对象关系变得复杂,可能导致调试困难。


适用场景


  • 变乱驱动系统

    • 如 GUI 程序、游戏引擎等。

  • 模型-视图结构

    • 数据模型的厘革关照视图更新。

  • 分布式系统

    • 如多个服务监听同一个变乱源。


总结

观察者模式通过定义一对多的依赖关系,解决了对象之间的动态联动问题,是变乱驱动系统中非常重要的设计模式。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

滴水恩情

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表