设计模式(C++)详解——观察者模式(Observer)(1) - 教程

观察者模式(Observer)深度解析:从理论到C++实战

1. 背景与核心概念

1.1 设计模式的起源与发展

观察者模式是软件工程中最经典、最常用的设计模式之一,它的历史可以追溯到面向对象编程的早期阶段。让我们回顾一下它的发展历程:

时期主要贡献应用场景技术特点
1970sSmalltalk MVC框架GUI应用程序模型-视图分离
1994GoF《设计模式》事件处理系统标准化模式描述
2000s.NET事件委托桌面应用开发语言级支持
2010s响应式编程Web前端、移动端数据流驱动

观察者模式的核心思想源于现实世界中的订阅-发布机制。就像报纸订阅一样:

  • 出版社(主题)维护订阅者列表
  • 读者(观察者)可以订阅或取消订阅
  • 新报纸出版时,所有订阅者自动收到通知

1.2 模式定义与关键角色

观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

让我们用Mermaid类图来理解各个角色的关系:

维护观察者列表
Subject
+attach(Observer* observer) : void
+detach(Observer* observer) : void
+notify() : void
ConcreteSubject
-state : int
+getState() : int
+setState(int state) : void
«interface»
Observer
+update(Subject* subject) : void
ConcreteObserver
-observerState : int
+update(Subject* subject) : void

关键角色解析

  • Subject(主题):维护观察者列表,提供添加、删除和通知观察者的接口
  • ConcreteSubject(具体主题):存储感兴趣的状态,状态改变时通知观察者
  • Observer(观察者):为所有具体观察者定义更新接口
  • ConcreteObserver(具体观察者):维护与主题状态一致的自身状态

1.3 MVC架构中的核心地位

观察者模式是MVC(Model-View-Controller)架构的核心机制:

通知更新
通知更新
通知更新
修改数据
Model 数据模型
View 视图1
View 视图2
View 视图3
Controller 控制器

在这种架构中:

  • Model 充当主题角色,维护业务数据和状态
  • View 充当观察者角色,监听Model的变化并更新显示
  • Controller 处理用户输入,修改Model状态

2. 设计意图与考量

2.1 核心设计目标

观察者模式的设计主要围绕以下几个目标:

1. 解耦性

  • 主题不需要知道观察者的具体类
  • 观察者可以独立变化和复用
  • 降低系统各部分之间的依赖

2. 动态关系

  • 运行时可以动态添加、删除观察者
  • 观察者关系可以随时改变
  • 支持灵活的订阅机制

3. 广播通信

  • 支持一对多的通信模式
  • 主题变化自动通知所有观察者
  • 避免手动维护更新逻辑

2.2 生命周期管理的挑战

观察者模式中最棘手的问题就是生命周期管理。考虑以下场景:

// 危险代码示例:悬空指针问题
Subject* subject = new Subject();
Observer* observer = new ConcreteObserver();
subject->attach(observer);  // 主题持有观察者指针
// 之后某个时刻...
delete observer;  // 观察者被销毁
// 但主题仍然持有已销毁对象的指针!
subject->notify();  // 灾难:访问已释放内存

解决方案对比

方案优点缺点适用场景
原始指针简单直接,无额外开销容易产生悬空指针简单场景,生命周期明确
shared_ptr自动内存管理循环引用导致内存泄漏需要共享所有权的场景
weak_ptr避免循环引用,安全使用稍复杂观察者模式推荐方案

2.3 性能与扩展性权衡

通知性能考量

  • 观察者数量增加时,通知开销线性增长
  • 可能需要支持按优先级通知
  • 考虑异步通知机制避免阻塞

扩展性设计

  • 支持不同类型的观察者
  • 允许观察者过滤感兴趣的事件
  • 提供批量更新机制

3. 实例与应用场景

3.1 案例一:股票价格监控系统

这是一个典型的观察者模式应用,多个投资者监控同一支股票的价格变化。

#include <iostream>
  #include <memory>
    #include <vector>
      #include <algorithm>
        #include <string>
          #include <unordered_map>
            // 前向声明
            class StockSubject;
            /**
            * @brief 观察者接口
            *
            * 定义观察者必须实现的更新接口,用于接收主题状态变化的通知。
            */
            class StockObserver : public std::enable_shared_from_this<StockObserver> {
              public:
              virtual ~StockObserver() = default;
              /**
              * @brief 更新方法
              *
              * 当观察的主题状态发生变化时,主题会调用此方法通知观察者。
              *
              * @in:
              *   - subject: 发生状态变化的主题对象指针
              */
              virtual void update(const StockSubject* subject) = 0;
              /**
              * @brief 获取观察者名称
              *
              * @return:观察者的标识名称
              */
              virtual std::string getName() const = 0;
              };
              /**
              * @brief 股票主题抽象基类
              *
              * 维护观察者列表,提供观察者的注册、注销和通知功能。
              */
              class StockSubject {
              protected:
              std::string stock_symbol_;    ///< 股票代码
              double current_price_;        ///< 当前价格
              /**
              * @brief 观察者列表(使用weak_ptr避免循环引用)
              */
              std::vector<std::weak_ptr<StockObserver>> observers_;
                public:
                /**
                * @brief 构造函数
                *
                * @in:
                *   - symbol: 股票代码
                *   - initial_price: 初始价格
                */
                StockSubject(const std::string& symbol, double initial_price)
                : stock_symbol_(symbol), current_price_(initial_price) {}
                virtual ~StockSubject() = default;
                /**
                * @brief 注册观察者
                *
                * 将观察者添加到观察者列表中,使其能够接收状态更新通知。
                *
                * @in:
                *   - observer: 要注册的观察者共享指针
                */
                void attach(const std::shared_ptr<StockObserver>& observer) {
                  // 检查是否已经注册
                  auto it = std::find_if(observers_.begin(), observers_.end(),
                  [&observer](const std::weak_ptr<StockObserver>& wp) {
                    return !wp.expired() && wp.lock() == observer;
                    });
                    if (it == observers_.end()) {
                    observers_.emplace_back(observer);
                    std::cout << "观察者 " << observer->getName()
                      << " 开始监控股票 " << stock_symbol_ << std::endl;
                      }
                      }
                      /**
                      * @brief 注销观察者
                      *
                      * 从观察者列表中移除指定的观察者,使其不再接收通知。
                      *
                      * @in:
                      *   - observer: 要注销的观察者共享指针
                      */
                      void detach(const std::shared_ptr<StockObserver>& observer) {
                        observers_.erase(
                        std::remove_if(observers_.begin(), observers_.end(),
                        [&observer](const std::weak_ptr<StockObserver>& wp) {
                          return wp.expired() || wp.lock() == observer;
                          }),
                          observers_.end());
                          std::cout << "观察者 " << observer->getName()
                            << " 停止监控股票 " << stock_symbol_ << std::endl;
                            }
                            /**
                            * @brief 通知所有观察者
                            *
                            * 遍历观察者列表,调用每个观察者的update方法。
                            * 自动清理已失效的观察者引用。
                            */
                            void notify() {
                            // 移除已失效的观察者
                            observers_.erase(
                            std::remove_if(observers_.begin(), observers_.end(),
                            [](const std::weak_ptr<StockObserver>& wp) {
                              return wp.expired();
                              }),
                              observers_.end());
                              // 通知所有有效观察者
                              for (auto& weak_observer : observers_) {
                              if (auto observer = weak_observer.lock()) {
                              observer->update(this);
                              }
                              }
                              }
                              /**
                              * @brief 获取股票代码
                              *
                              * @return:股票代码字符串
                              */
                              std::string getSymbol() const { return stock_symbol_; }
                              /**
                              * @brief 获取当前价格
                              *
                              * @return:当前股票价格
                              */
                              double getPrice() const { return current_price_; }
                              /**
                              * @brief 获取观察者数量
                              *
                              * @return:当前注册的观察者数量
                              */
                              size_t getObserverCount() const {
                              return std::count_if(observers_.begin(), observers_.end(),
                              [](const std::weak_ptr<StockObserver>& wp) {
                                return !wp.expired();
                                });
                                }
                                };
                                /**
                                * @brief 具体股票主题
                                *
                                * 代表一支具体的股票,可以更新价格并通知所有观察者。
                                */
                                class ConcreteStock : public StockSubject {
                                public:
                                /**
                                * @brief 构造函数
                                *
                                * @in:
                                *   - symbol: 股票代码
                                *   - initial_price: 初始价格
                                */
                                ConcreteStock(const std::string& symbol, double initial_price)
                                : StockSubject(symbol, initial_price) {}
                                /**
                                * @brief 更新股票价格
                                *
                                * 设置新的股票价格,如果价格发生变化则通知所有观察者。
                                *
                                * @in:
                                *   - new_price: 新的股票价格
                                */
                                void setPrice(double new_price) {
                                if (current_price_ != new_price) {
                                double old_price = current_price_;
                                current_price_ = new_price;
                                std::cout << "\n股票 " << stock_symbol_
                                << " 价格变化: " << old_price
                                << " -> " << new_price << std::endl;
                                  // 通知所有观察者
                                  notify();
                                  }
                                  }
                                  };
                                  /**
                                  * @brief 投资者观察者
                                  *
                                  * 代表监控股票价格的投资者,在价格变化时执行相应的投资策略。
                                  */
                                  class Investor : public StockObserver {
                                  private:
                                  std::string name_;                    ///< 投资者名称
                                  double buy_threshold_;               ///< 买入阈值
                                  double sell_threshold_;              ///< 卖出阈值
                                  std::string last_action_;            ///< 上次操作记录
                                  public:
                                  /**
                                  * @brief 构造函数
                                  *
                                  * @in:
                                  *   - name: 投资者名称
                                  *   - buy_threshold: 价格低于此值时考虑买入
                                  *   - sell_threshold: 价格高于此值时考虑卖出
                                  */
                                  Investor(const std::string& name, double buy_threshold, double sell_threshold)
                                  : name_(name), buy_threshold_(buy_threshold),
                                  sell_threshold_(sell_threshold), last_action_("无操作") {}
                                  /**
                                  * @brief 更新方法实现
                                  *
                                  * 接收股票价格变化通知,根据投资策略决定是否买入或卖出。
                                  *
                                  * @in:
                                  *   - subject: 发生价格变化的股票主题
                                  */
                                  void update(const StockSubject* subject) override {
                                  double current_price = subject->getPrice();
                                  const std::string& symbol = subject->getSymbol();
                                  std::cout << "[" << name_ << "] 收到通知: "
                                  << symbol << " 当前价格 = " << current_price << std::endl;
                                  // 投资策略决策
                                  if (current_price <= buy_threshold_) {
                                  last_action_ = "买入";
                                  std::cout << "  → 决策: " << last_action_ << " " << symbol
                                  << " (价格 <= " << buy_threshold_ << ")" << std::endl;
                                  } else if (current_price >= sell_threshold_) {
                                  last_action_ = "卖出";
                                  std::cout << "  → 决策: " << last_action_ << " " << symbol
                                  << " (价格 >= " << sell_threshold_ << ")" << std::endl;
                                    } else {
                                    last_action_ = "持有";
                                    std::cout << "  → 决策: " << last_action_ << " " << symbol
                                    << " (观望中)" << std::endl;
                                    }
                                    }
                                    /**
                                    * @brief 获取观察者名称
                                    *
                                    * @return:投资者名称
                                    */
                                    std::string getName() const override {
                                    return name_;
                                    }
                                    /**
                                    * @brief 获取上次操作
                                    *
                                    * @return:上次投资操作描述
                                    */
                                    std::string getLastAction() const {
                                    return last_action_;
                                    }
                                    };
                                    /**
                                    * @brief 机构观察者
                                    *
                                    * 代表机构投资者,具有更复杂的监控逻辑和报表功能。
                                    */
                                    class Institution : public StockObserver {
                                    private:
                                    std::string institution_name_;       ///< 机构名称
                                    std::unordered_map<std::string, double> price_history_;  ///< 价格历史记录
                                      public:
                                      /**
                                      * @brief 构造函数
                                      *
                                      * @in:
                                      *   - name: 机构名称
                                      */
                                      explicit Institution(const std::string& name)
                                      : institution_name_(name) {}
                                      /**
                                      * @brief 更新方法实现
                                      *
                                      * 记录价格历史并生成分析报告。
                                      *
                                      * @in:
                                      *   - subject: 发生价格变化的股票主题
                                      */
                                      void update(const StockSubject* subject) override {
                                      const std::string& symbol = subject->getSymbol();
                                      double current_price = subject->getPrice();
                                      // 记录价格历史
                                      auto it = price_history_.find(symbol);
                                      if (it != price_history_.end()) {
                                      double old_price = it->second;
                                      double change = ((current_price - old_price) / old_price) * 100;
                                      std::cout << "[" << institution_name_ << "] 分析报告 - " << symbol
                                      << ": " << old_price << " → " << current_price
                                      << " (" << (change >= 0 ? "+" : "") << change << "%)" << std::endl;
                                        }
                                        price_history_[symbol] = current_price;
                                        }
                                        /**
                                        * @brief 获取观察者名称
                                        *
                                        * @return:机构名称
                                        */
                                        std::string getName() const override {
                                        return institution_name_;
                                        }
                                        /**
                                        * @brief 生成详细报告
                                        *
                                        * @return:包含所有监控股票的分析报告
                                        */
                                        std::string generateReport() const {
                                        std::string report = institution_name_ + " 监控报告:\n";
                                        for (const auto& entry : price_history_) {
                                        report += "  " + entry.first + ": " + std::to_string(entry.second) + "\n";
                                        }
                                        return report;
                                        }
                                        };
                                        /**
                                        * @brief 主函数 - 股票监控系统演示
                                        *
                                        * 演示观察者模式在金融监控系统中的应用,展示动态订阅和自动通知机制。
                                        *
                                        * @return:程序退出码
                                        */
                                        int main() {
                                        std::cout << "=== 股票价格监控系统演示 ===" << std::endl;
                                        // 创建股票主题
                                        auto apple_stock = std::make_shared<ConcreteStock>("AAPL", 150.0);
                                          auto google_stock = std::make_shared<ConcreteStock>("GOOGL", 2800.0);
                                            // 创建投资者观察者
                                            auto investor1 = std::make_shared<Investor>("张投资者", 145.0, 160.0);
                                              auto investor2 = std::make_shared<Investor>("李投资者", 140.0, 155.0);
                                                auto institution = std::make_shared<Institution>("量子基金");
                                                  std::cout << "\n--- 初始订阅阶段 ---" << std::endl;
                                                  // 投资者订阅股票
                                                  apple_stock->attach(investor1);
                                                  apple_stock->attach(investor2);
                                                  apple_stock->attach(institution);
                                                  google_stock->attach(investor1);
                                                  google_stock->attach(institution);
                                                  std::cout << "\nAAPL 观察者数量: " << apple_stock->getObserverCount() << std::endl;
                                                    std::cout << "GOOGL 观察者数量: " << google_stock->getObserverCount() << std::endl;
                                                      std::cout << "\n--- 价格变化阶段 ---" << std::endl;
                                                      // 模拟价格变化
                                                      apple_stock->setPrice(148.5);  // 小幅下跌
                                                      apple_stock->setPrice(142.0);  // 大幅下跌
                                                      apple_stock->setPrice(158.0);  // 大幅上涨
                                                      google_stock->setPrice(2750.0); // 小幅下跌
                                                      google_stock->setPrice(2850.0); // 上涨
                                                      std::cout << "\n--- 动态订阅调整 ---" << std::endl;
                                                      // 动态取消订阅
                                                      apple_stock->detach(investor2);
                                                      std::cout << "AAPL 观察者数量: " << apple_stock->getObserverCount() << std::endl;
                                                        // 继续价格变化
                                                        apple_stock->setPrice(162.0);
                                                        std::cout << "\n--- 机构报告生成 ---" << std::endl;
                                                        std::cout << institution->generateReport();
                                                          std::cout << "\n--- 生命周期安全测试 ---" << std::endl;
                                                          {
                                                          // 创建临时观察者
                                                          auto temp_investor = std::make_shared<Investor>("临时投资者", 150.0, 165.0);
                                                            apple_stock->attach(temp_investor);
                                                            std::cout << "临时观察者订阅后,AAPL 观察者数量: "
                                                            << apple_stock->getObserverCount() << std::endl;
                                                              // temp_investor 离开作用域自动销毁
                                                              }
                                                              // 即使临时观察者已销毁,这里也不会崩溃
                                                              apple_stock->setPrice(155.0);
                                                              std::cout << "临时观察者销毁后,AAPL 观察者数量: "
                                                              << apple_stock->getObserverCount() << std::endl;
                                                                std::cout << "\n=== 演示完成 ===" << std::endl;
                                                                return 0;
                                                                }

Mermaid时序图

AppleStock张投资者李投资者量子基金初始状态:价格150.0attach(张投资者)attach(李投资者)attach(量子基金)setPrice(148.5)update()update()update()所有观察者收到价格下跌通知setPrice(142.0)update()update()update()detach(李投资者)setPrice(158.0)update()update()李投资者已取消订阅,不再接收通知AppleStock张投资者李投资者量子基金

3.2 案例二:游戏引擎事件系统

游戏引擎中广泛使用观察者模式来处理各种游戏事件。

#include <iostream>
  #include <memory>
    #include <vector>
      #include <string>
        #include <unordered_map>
          #include <algorithm>
            // 游戏事件类型枚举
            enum class EventType {
            PLAYER_SPAWN,
            PLAYER_DEATH,
            ITEM_PICKUP,
            LEVEL_COMPLETE,
            ACHIEVEMENT_UNLOCKED
            };
            /**
            * @brief 游戏事件数据基类
            *
            * 所有具体游戏事件数据的基类,提供基本的事件信息。
            */
            struct GameEvent {
            EventType type;             ///< 事件类型
            double timestamp;          ///< 事件时间戳
            virtual ~GameEvent() = default;
            /**
            * @brief 获取事件描述
            *
            * @return:事件的文字描述
            */
            virtual std::string getDescription() const = 0;
            };
            /**
            * @brief 玩家生成事件
            */
            struct PlayerSpawnEvent : public GameEvent {
            std::string player_name;    ///< 玩家名称
            int spawn_point_id;         ///< 生成点ID
            PlayerSpawnEvent(const std::string& name, int spawn_id)
            : player_name(name), spawn_point_id(spawn_id) {
            type = EventType::PLAYER_SPAWN;
            }
            std::string getDescription() const override {
            return "玩家 " + player_name + " 在生成点 " + std::to_string(spawn_point_id) + " 生成";
            }
            };
            /**
            * @brief 玩家死亡事件
            */
            struct PlayerDeathEvent : public GameEvent {
            std::string player_name;    ///< 玩家名称
            std::string killer_name;    ///< 击杀者名称
            std::string cause;          ///< 死亡原因
            PlayerDeathEvent(const std::string& player, const std::string& killer, const std::string& death_cause)
            : player_name(player), killer_name(killer), cause(death_cause) {
            type = EventType::PLAYER_DEATH;
            }
            std::string getDescription() const override {
            return "玩家 " + player_name + " 被 " + killer_name + " 击杀 (" + cause + ")";
            }
            };
            /**
            * @brief 成就解锁事件
            */
            struct AchievementEvent : public GameEvent {
            std::string achievement_id;  ///< 成就ID
            std::string achievement_name; ///< 成就名称
            int points;                 ///< 成就点数
            AchievementEvent(const std::string& id, const std::string& name, int pts)
            : achievement_id(id), achievement_name(name), points(pts) {
            type = EventType::ACHIEVEMENT_UNLOCKED;
            }
            std::string getDescription() const override {
            return "解锁成就: " + achievement_name + " (" + std::to_string(points) + "点)";
            }
            };
            // 前向声明
            class EventManager;
            /**
            * @brief 游戏事件观察者接口
            *
            * 游戏系统中各种组件通过实现此接口来监听感兴趣的游戏事件。
            */
            class GameEventListener {
            public:
            virtual ~GameEventListener() = default;
            /**
            * @brief 事件处理接口
            *
            * @in:
            *   - event: 发生的事件对象
            *   - manager: 事件管理器,用于触发新事件
            */
            virtual void onEvent(const std::shared_ptr<GameEvent>& event,
              EventManager* manager) = 0;
              /**
              * @brief 获取监听器名称
              *
              * @return:监听器标识名称
              */
              virtual std::string getName() const = 0;
              /**
              * @brief 获取感兴趣的事件类型
              *
              * @return:该监听器关心的事件类型列表
              */
              virtual std::vector<EventType> getInterestedEvents() const = 0;
                };
                /**
                * @brief 事件管理器
                *
                * 游戏事件系统的核心,负责事件的发布和观察者管理。
                */
                class EventManager {
                private:
                /**
                * @brief 事件类型到观察者列表的映射
                */
                std::unordered_map<EventType,
                std::vector<std::weak_ptr<GameEventListener>>> event_listeners_;
                  public:
                  /**
                  * @brief 注册事件监听器
                  *
                  * 将监听器注册到其感兴趣的所有事件类型上。
                  *
                  * @in:
                  *   - listener: 要注册的事件监听器
                  */
                  void registerListener(const std::shared_ptr<GameEventListener>& listener) {
                    for (EventType event_type : listener->getInterestedEvents()) {
                    event_listeners_[event_type].emplace_back(listener);
                    std::cout << "注册监听器: " << listener->getName()
                      << " -> 事件类型: " << static_cast<int>(event_type) << std::endl;
                        }
                        }
                        /**
                        * @brief 取消注册事件监听器
                        *
                        * 从所有事件类型中移除指定的监听器。
                        *
                        * @in:
                        *   - listener: 要取消注册的事件监听器
                        */
                        void unregisterListener(const std::shared_ptr<GameEventListener>& listener) {
                          for (auto& pair : event_listeners_) {
                          auto& listeners = pair.second;
                          listeners.erase(
                          std::remove_if(listeners.begin(), listeners.end(),
                          [&listener](const std::weak_ptr<GameEventListener>& wp) {
                            return wp.expired() || wp.lock() == listener;
                            }),
                            listeners.end());
                            }
                            std::cout << "取消注册监听器: " << listener->getName() << std::endl;
                              }
                              /**
                              * @brief 发布事件
                              *
                              * 将事件发送给所有注册的对应类型监听器。
                              *
                              * @in:
                              *   - event: 要发布的事件对象
                              */
                              void publishEvent(const std::shared_ptr<GameEvent>& event) {
                                std::cout << "\n[事件发布] " << event->getDescription() << std::endl;
                                  auto it = event_listeners_.find(event->type);
                                  if (it != event_listeners_.end()) {
                                  // 清理失效的监听器
                                  auto& listeners = it->second;
                                  listeners.erase(
                                  std::remove_if(listeners.begin(), listeners.end(),
                                  [](const std::weak_ptr<GameEventListener>& wp) {
                                    return wp.expired();
                                    }),
                                    listeners.end());
                                    // 通知所有有效监听器
                                    for (auto& weak_listener : listeners) {
                                    if (auto listener = weak_listener.lock()) {
                                    listener->onEvent(event, this);
                                    }
                                    }
                                    }
                                    }
                                    /**
                                    * @brief 获取监听器统计信息
                                    *
                                    * @return:各事件类型的监听器数量统计
                                    */
                                    std::string getStats() const {
                                    std::string stats = "事件监听器统计:\n";
                                    for (const auto& pair : event_listeners_) {
                                    int count = std::count_if(pair.second.begin(), pair.second.end(),
                                    [](const std::weak_ptr<GameEventListener>& wp) {
                                      return !wp.expired();
                                      });
                                      stats += "  事件类型 " + std::to_string(static_cast<int>(pair.first))
                                        + ": " + std::to_string(count) + " 个监听器\n";
                                        }
                                        return stats;
                                        }
                                        };
                                        /**
                                        * @brief 成就系统
                                        *
                                        * 监听游戏事件并解锁相应的成就。
                                        */
                                        class AchievementSystem : public GameEventListener {
                                        private:
                                        std::unordered_map<std::string, bool> unlocked_achievements_;  ///< 已解锁成就记录
                                          int total_points_;                                             ///< 总成就点数
                                          public:
                                          AchievementSystem() : total_points_(0) {
                                          // 初始化成就列表
                                          unlocked_achievements_ = {
                                          {"first_blood", false},
                                          {"veteran", false},
                                          {"collector", false}
                                          };
                                          }
                                          void onEvent(const std::shared_ptr<GameEvent>& event,
                                            EventManager* manager) override {
                                            switch (event->type) {
                                            case EventType::PLAYER_DEATH: {
                                            // 检查是否是第一次击杀
                                            if (!unlocked_achievements_["first_blood"]) {
                                            unlocked_achievements_["first_blood"] = true;
                                            total_points_ += 10;
                                            // 发布成就解锁事件
                                            auto achievement_event = std::make_shared<AchievementEvent>(
                                              "first_blood", "第一滴血", 10);
                                              manager->publishEvent(achievement_event);
                                              }
                                              break;
                                              }
                                              case EventType::PLAYER_SPAWN: {
                                              auto spawn_event = std::dynamic_pointer_cast<PlayerSpawnEvent>(event);
                                                if (spawn_event && spawn_event->spawn_point_id > 5 &&
                                                !unlocked_achievements_["veteran"]) {
                                                unlocked_achievements_["veteran"] = true;
                                                total_points_ += 20;
                                                auto achievement_event = std::make_shared<AchievementEvent>(
                                                  "veteran", "战场老兵", 20);
                                                  manager->publishEvent(achievement_event);
                                                  }
                                                  break;
                                                  }
                                                  case EventType::ITEM_PICKUP: {
                                                  // 简单的物品收集成就逻辑
                                                  if (!unlocked_achievements_["collector"]) {
                                                  unlocked_achievements_["collector"] = true;
                                                  total_points_ += 15;
                                                  auto achievement_event = std::make_shared<AchievementEvent>(
                                                    "collector", "收藏家", 15);
                                                    manager->publishEvent(achievement_event);
                                                    }
                                                    break;
                                                    }
                                                    default:
                                                    break;
                                                    }
                                                    }
                                                    std::string getName() const override {
                                                    return "成就系统";
                                                    }
                                                    std::vector<EventType> getInterestedEvents() const override {
                                                      return {
                                                      EventType::PLAYER_DEATH,
                                                      EventType::PLAYER_SPAWN,
                                                      EventType::ITEM_PICKUP
                                                      };
                                                      }
                                                      /**
                                                      * @brief 获取成就系统状态
                                                      *
                                                      * @return:成就解锁状态和点数统计
                                                      */
                                                      std::string getStatus() const {
                                                      std::string status = "成就系统状态:\n";
                                                      status += "  总点数: " + std::to_string(total_points_) + "\n";
                                                      status += "  已解锁成就:\n";
                                                      for (const auto& achievement : unlocked_achievements_) {
                                                      status += "    " + achievement.first + ": "
                                                      + (achievement.second ? "已解锁" : "未解锁") + "\n";
                                                      }
                                                      return status;
                                                      }
                                                      };
                                                      /**
                                                      * @brief 统计系统
                                                      *
                                                      * 收集游戏统计数据,如击杀数、死亡数等。
                                                      */
                                                      class StatisticsSystem : public GameEventListener {
                                                      private:
                                                      int total_kills_;           ///< 总击杀数
                                                      int total_deaths_;          ///< 总死亡数
                                                      int total_spawns_;          ///< 总生成次数
                                                      public:
                                                      StatisticsSystem() : total_kills_(0), total_deaths_(0), total_spawns_(0) {}
                                                      void onEvent(const std::shared_ptr<GameEvent>& event,
                                                        EventManager* manager) override {
                                                        switch (event->type) {
                                                        case EventType::PLAYER_DEATH:
                                                        total_deaths_++;
                                                        break;
                                                        case EventType::PLAYER_SPAWN:
                                                        total_spawns_++;
                                                        break;
                                                        default:
                                                        break;
                                                        }
                                                        }
                                                        std::string getName() const override {
                                                        return "统计系统";
                                                        }
                                                        std::vector<EventType> getInterestedEvents() const override {
                                                          return {
                                                          EventType::PLAYER_DEATH,
                                                          EventType::PLAYER_SPAWN
                                                          };
                                                          }
                                                          /**
                                                          * @brief 获取统计报告
                                                          *
                                                          * @return:游戏统计数据报告
                                                          */
                                                          std::string getReport() const {
                                                          return "游戏统计:\n  生成次数: " + std::to_string(total_spawns_) +
                                                          "\n  死亡次数: " + std::to_string(total_deaths_) +
                                                          "\n  K/D比率: " + (total_deaths_ > 0 ?
                                                          std::to_string(static_cast<double>(total_kills_) / total_deaths_) : "N/A");
                                                            }
                                                            };
                                                            /**
                                                            * @brief 用户界面系统
                                                            *
                                                            * 在游戏UI中显示事件通知。
                                                            */
                                                            class UISystem : public GameEventListener {
                                                            public:
                                                            void onEvent(const std::shared_ptr<GameEvent>& event,
                                                              EventManager* manager) override {
                                                              std::cout << "[UI通知] " << event->getDescription() << std::endl;
                                                                }
                                                                std::string getName() const override {
                                                                return "UI系统";
                                                                }
                                                                std::vector<EventType> getInterestedEvents() const override {
                                                                  // UI系统关心所有事件类型
                                                                  return {
                                                                  EventType::PLAYER_SPAWN,
                                                                  EventType::PLAYER_DEATH,
                                                                  EventType::ITEM_PICKUP,
                                                                  EventType::LEVEL_COMPLETE,
                                                                  EventType::ACHIEVEMENT_UNLOCKED
                                                                  };
                                                                  }
                                                                  };
                                                                  /**
                                                                  * @brief 主函数 - 游戏事件系统演示
                                                                  *
                                                                  * 演示观察者模式在游戏事件系统中的应用,展示多类型事件的处理机制。
                                                                  *
                                                                  * @return:程序退出码
                                                                  */
                                                                  int main() {
                                                                  std::cout << "=== 游戏引擎事件系统演示 ===" << std::endl;
                                                                  // 创建事件管理器
                                                                  EventManager event_manager;
                                                                  // 创建各种游戏系统
                                                                  auto achievement_system = std::make_shared<AchievementSystem>();
                                                                    auto stats_system = std::make_shared<StatisticsSystem>();
                                                                      auto ui_system = std::make_shared<UISystem>();
                                                                        // 注册系统到事件管理器
                                                                        std::cout << "\n--- 系统注册阶段 ---" << std::endl;
                                                                        event_manager.registerListener(achievement_system);
                                                                        event_manager.registerListener(stats_system);
                                                                        event_manager.registerListener(ui_system);
                                                                        std::cout << event_manager.getStats();
                                                                        std::cout << "\n--- 游戏事件模拟 ---" << std::endl;
                                                                        // 模拟游戏事件序列
                                                                        auto spawn_event1 = std::make_shared<PlayerSpawnEvent>("玩家1", 1);
                                                                          event_manager.publishEvent(spawn_event1);
                                                                          auto spawn_event2 = std::make_shared<PlayerSpawnEvent>("玩家2", 6); // 高级生成点
                                                                            event_manager.publishEvent(spawn_event2);
                                                                            auto death_event1 = std::make_shared<PlayerDeathEvent>("玩家1", "玩家2", "爆头");
                                                                              event_manager.publishEvent(death_event1);
                                                                              // 模拟物品拾取事件
                                                                              auto pickup_event = std::make_shared<GameEvent>();
                                                                                pickup_event->type = EventType::ITEM_PICKUP;
                                                                                event_manager.publishEvent(pickup_event);
                                                                                std::cout << "\n--- 系统状态报告 ---" << std::endl;
                                                                                std::cout << achievement_system->getStatus() << std::endl;
                                                                                  std::cout << stats_system->getReport() << std::endl;
                                                                                    std::cout << "\n--- 动态系统管理 ---" << std::endl;
                                                                                    // 动态移除UI系统
                                                                                    event_manager.unregisterListener(ui_system);
                                                                                    // 后续事件不再通知UI系统
                                                                                    auto death_event2 = std::make_shared<PlayerDeathEvent>("玩家2", "玩家1", "近战");
                                                                                      event_manager.publishEvent(death_event2);
                                                                                      std::cout << event_manager.getStats();
                                                                                      std::cout << "\n=== 演示完成 ===" << std::endl;
                                                                                      return 0;
                                                                                      }

Mermaid流程图

游戏事件发生
EventManager.publishEvent
查找对应事件类型的监听器列表
清理已失效的监听器
遍历有效监听器
监听器处理事件?
调用onEvent方法
跳过此监听器
监听器可能发布新事件
所有监听器处理完成?
事件处理完成

3.3 案例三:配置管理系统

企业级配置管理系统使用观察者模式实现配置热更新。

#include <iostream>
  #include <memory>
    #include <vector>
      #include <string>
        #include <unordered_map>
          #include <functional>
            #include <sstream>
              /**
              * @brief 配置变更观察者接口
              *
              * 组件通过实现此接口来监听配置变化并自动更新自身状态。
              */
              class ConfigChangeListener {
              public:
              virtual ~ConfigChangeListener() = default;
              /**
              * @brief 配置变更回调
              *
              * 当监听的配置项发生变化时调用此方法。
              *
              * @in:
              *   - key: 发生变化的配置键
              *   - old_value: 旧的配置值
              *   - new_value: 新的配置值
              */
              virtual void onConfigChanged(const std::string& key,
              const std::string& old_value,
              const std::string& new_value) = 0;
              /**
              * @brief 获取监听器名称
              *
              * @return:监听器标识名称
              */
              virtual std::string getName() const = 0;
              /**
              * @brief 获取关心的配置键
              *
              * @return:该监听器关心的配置键列表
              */
              virtual std::vector<std::string> getWatchedKeys() const = 0;
                };
                /**
                * @brief 配置管理器
                *
                * 管理应用程序的配置数据,支持配置热更新和观察者通知。
                */
                class ConfigManager {
                private:
                std::unordered_map<std::string, std::string> config_data_;  ///< 配置数据存储
                  /**
                  * @brief 配置键到观察者列表的映射
                  */
                  std::unordered_map<std::string,
                  std::vector<std::weak_ptr<ConfigChangeListener>>> key_listeners_;
                    /**
                    * @brief 全局观察者列表(监听所有配置变化)
                    */
                    std::vector<std::weak_ptr<ConfigChangeListener>> global_listeners_;
                      public:
                      /**
                      * @brief 设置配置值
                      *
                      * 设置指定配置键的值,如果值发生变化则通知所有观察者。
                      *
                      * @in:
                      *   - key: 配置键
                      *   - value: 配置值
                      */
                      void setConfig(const std::string& key, const std::string& value) {
                      std::string old_value = getConfig(key, "");
                      if (old_value != value) {
                      config_data_[key] = value;
                      std::cout << "配置更新: " << key << " = " << value
                      << " (原值: " << (old_value.empty() ? "空" : old_value) << ")" << std::endl;
                      // 通知特定键的观察者
                      notifyKeyListeners(key, old_value, value);
                      // 通知全局观察者
                      notifyGlobalListeners(key, old_value, value);
                      }
                      }
                      /**
                      * @brief 获取配置值
                      *
                      * @in:
                      *   - key: 配置键
                      *   - default_value: 如果键不存在时返回的默认值
                      *
                      * @return:配置值或默认值
                      */
                      std::string getConfig(const std::string& key, const std::string& default_value = "") const {
                      auto it = config_data_.find(key);
                      return it != config_data_.end() ? it->second : default_value;
                      }
                      /**
                      * @brief 注册键监听器
                      *
                      * 注册观察者监听特定配置键的变化。
                      *
                      * @in:
                      *   - key: 要监听的配置键
                      *   - listener: 配置变更观察者
                      */
                      void registerKeyListener(const std::string& key,
                      const std::shared_ptr<ConfigChangeListener>& listener) {
                        key_listeners_[key].emplace_back(listener);
                        std::cout << "注册键监听: " << listener->getName() << " -> " << key << std::endl;
                          }
                          /**
                          * @brief 注册全局监听器
                          *
                          * 注册观察者监听所有配置键的变化。
                          *
                          * @in:
                          *   - listener: 配置变更观察者
                          */
                          void registerGlobalListener(const std::shared_ptr<ConfigChangeListener>& listener) {
                            global_listeners_.emplace_back(listener);
                            std::cout << "注册全局监听: " << listener->getName() << std::endl;
                              }
                              /**
                              * @brief 批量注册监听器
                              *
                              * 根据观察者关心的键列表自动注册监听。
                              *
                              * @in:
                              *   - listener: 配置变更观察者
                              */
                              void registerListener(const std::shared_ptr<ConfigChangeListener>& listener) {
                                for (const auto& key : listener->getWatchedKeys()) {
                                registerKeyListener(key, listener);
                                }
                                }
                                /**
                                * @brief 获取配置快照
                                *
                                * @return:当前所有配置的字符串表示
                                */
                                std::string getConfigSnapshot() const {
                                std::stringstream ss;
                                ss << "当前配置快照:\n";
                                for (const auto& entry : config_data_) {
                                ss << "  " << entry.first << " = " << entry.second << "\n";
                                }
                                return ss.str();
                                }
                                private:
                                /**
                                * @brief 通知键监听器
                                *
                                * 通知监听特定配置键的观察者。
                                *
                                * @in:
                                *   - key: 发生变化的配置键
                                *   - old_value: 旧值
                                *   - new_value: 新值
                                */
                                void notifyKeyListeners(const std::string& key,
                                const std::string& old_value,
                                const std::string& new_value) {
                                auto it = key_listeners_.find(key);
                                if (it != key_listeners_.end()) {
                                auto& listeners = it->second;
                                // 清理失效的监听器
                                listeners.erase(
                                std::remove_if(listeners.begin(), listeners.end(),
                                [](const std::weak_ptr<ConfigChangeListener>& wp) {
                                  return wp.expired();
                                  }),
                                  listeners.end());
                                  // 通知有效监听器
                                  for (auto& weak_listener : listeners) {
                                  if (auto listener = weak_listener.lock()) {
                                  listener->onConfigChanged(key, old_value, new_value);
                                  }
                                  }
                                  }
                                  }
                                  /**
                                  * @brief 通知全局监听器
                                  *
                                  * 通知监听所有配置变化的观察者。
                                  *
                                  * @in:
                                  *   - key: 发生变化的配置键
                                  *   - old_value: 旧值
                                  *   - new_value: 新值
                                  */
                                  void notifyGlobalListeners(const std::string& key,
                                  const std::string& old_value,
                                  const std::string& new_value) {
                                  // 清理失效的监听器
                                  global_listeners_.erase(
                                  std::remove_if(global_listeners_.begin(), global_listeners_.end(),
                                  [](const std::weak_ptr<ConfigChangeListener>& wp) {
                                    return wp.expired();
                                    }),
                                    global_listeners_.end());
                                    // 通知有效监听器
                                    for (auto& weak_listener : global_listeners_) {
                                    if (auto listener = weak_listener.lock()) {
                                    listener->onConfigChanged(key, old_value, new_value);
                                    }
                                    }
                                    }
                                    };
                                    /**
                                    * @brief 数据库连接池
                                    *
                                    * 根据数据库配置变化动态调整连接池参数。
                                    */
                                    class DatabaseConnectionPool : public ConfigChangeListener {
                                    private:
                                    std::string pool_name_;                 ///< 连接池名称
                                    int max_connections_;                   ///< 最大连接数
                                    int timeout_seconds_;                   ///< 超时时间
                                    public:
                                    explicit DatabaseConnectionPool(const std::string& name)
                                    : pool_name_(name), max_connections_(10), timeout_seconds_(30) {}
                                    void onConfigChanged(const std::string& key,
                                    const std::string& old_value,
                                    const std::string& new_value) override {
                                    if (key == "db.max_connections") {
                                    int new_max = std::stoi(new_value);
                                    if (new_max != max_connections_) {
                                    std::cout << "[" << pool_name_ << "] 更新最大连接数: "
                                    << max_connections_ << " -> " << new_max << std::endl;
                                      max_connections_ = new_max;
                                      applyPoolConfig();
                                      }
                                      } else if (key == "db.timeout") {
                                      int new_timeout = std::stoi(new_value);
                                      if (new_timeout != timeout_seconds_) {
                                      std::cout << "[" << pool_name_ << "] 更新超时时间: "
                                      << timeout_seconds_ << " -> " << new_timeout << "秒" << std::endl;
                                        timeout_seconds_ = new_timeout;
                                        applyPoolConfig();
                                        }
                                        }
                                        }
                                        std::string getName() const override {
                                        return "数据库连接池[" + pool_name_ + "]";
                                        }
                                        std::vector<std::string> getWatchedKeys() const override {
                                          return {
                                          "db.max_connections",
                                          "db.timeout"
                                          };
                                          }
                                          /**
                                          * @brief 应用连接池配置
                                          *
                                          * 根据当前配置参数调整连接池状态。
                                          */
                                          void applyPoolConfig() {
                                          std::cout << "[" << pool_name_ << "] 应用配置: "
                                          << max_connections_ << "连接, "
                                          << timeout_seconds_ << "秒超时" << std::endl;
                                          }
                                          /**
                                          * @brief 获取连接池状态
                                          *
                                          * @return:连接池当前状态描述
                                          */
                                          std::string getStatus() const {
                                          return "连接池状态: " + std::to_string(max_connections_) + "连接, "
                                          + std::to_string(timeout_seconds_) + "秒超时";
                                          }
                                          };
                                          /**
                                          * @brief 日志系统
                                          *
                                          * 根据日志配置变化动态调整日志级别和输出目标。
                                          */
                                          class LogSystem : public ConfigChangeListener {
                                          private:
                                          std::string log_level_;                 ///< 当前日志级别
                                          std::string output_target_;             ///< 输出目标
                                          public:
                                          LogSystem() : log_level_("INFO"), output_target_("console") {}
                                          void onConfigChanged(const std::string& key,
                                          const std::string& old_value,
                                          const std::string& new_value) override {
                                          if (key == "log.level") {
                                          std::cout << "[日志系统] 更新日志级别: " << log_level_
                                          << " -> " << new_value << std::endl;
                                            log_level_ = new_value;
                                            applyLogConfig();
                                            } else if (key == "log.output") {
                                            std::cout << "[日志系统] 更新输出目标: " << output_target_
                                            << " -> " << new_value << std::endl;
                                              output_target_ = new_value;
                                              applyLogConfig();
                                              }
                                              }
                                              std::string getName() const override {
                                              return "日志系统";
                                              }
                                              std::vector<std::string> getWatchedKeys() const override {
                                                return {
                                                "log.level",
                                                "log.output"
                                                };
                                                }
                                                /**
                                                * @brief 应用日志配置
                                                *
                                                * 根据当前配置参数调整日志系统行为。
                                                */
                                                void applyLogConfig() {
                                                std::cout << "[日志系统] 应用配置: 级别=" << log_level_
                                                << ", 输出=" << output_target_ << std::endl;
                                                }
                                                /**
                                                * @brief 记录日志
                                                *
                                                * @in:
                                                *   - level: 日志级别
                                                *   - message: 日志消息
                                                */
                                                void log(const std::string& level, const std::string& message) {
                                                // 简单的级别过滤
                                                if (shouldLog(level)) {
                                                std::cout << "[" << level << "] " << message << std::endl;
                                                }
                                                }
                                                private:
                                                /**
                                                * @brief 检查是否应该记录指定级别的日志
                                                *
                                                * @in:
                                                *   - level: 要检查的日志级别
                                                *
                                                * @return:如果应该记录返回true
                                                */
                                                bool shouldLog(const std::string& level) const {
                                                static const std::unordered_map<std::string, int> level_priority = {
                                                  {"DEBUG", 0},
                                                  {"INFO", 1},
                                                  {"WARN", 2},
                                                  {"ERROR", 3},
                                                  {"FATAL", 4}
                                                  };
                                                  auto current_it = level_priority.find(log_level_);
                                                  auto check_it = level_priority.find(level);
                                                  if (current_it != level_priority.end() && check_it != level_priority.end()) {
                                                  return check_it->second >= current_it->second;
                                                  }
                                                  return false;
                                                  }
                                                  };
                                                  /**
                                                  * @brief 配置审计系统
                                                  *
                                                  * 记录所有配置变更的审计日志,用于安全监控。
                                                  */
                                                  class ConfigAuditSystem : public ConfigChangeListener {
                                                  public:
                                                  void onConfigChanged(const std::string& key,
                                                  const std::string& old_value,
                                                  const std::string& new_value) override {
                                                  std::cout << "[审计系统] 配置变更审计: " << key
                                                  << " = " << old_value << " -> " << new_value << std::endl;
                                                    // 在实际系统中,这里会将审计记录写入数据库或文件
                                                    writeAuditLog(key, old_value, new_value);
                                                    }
                                                    std::string getName() const override {
                                                    return "配置审计系统";
                                                    }
                                                    std::vector<std::string> getWatchedKeys() const override {
                                                      // 审计系统关心所有配置键
                                                      return {}; // 空列表表示监听所有键(通过全局监听注册)
                                                      }
                                                      private:
                                                      /**
                                                      * @brief 写入审计日志
                                                      *
                                                      * @in:
                                                      *   - key: 配置键
                                                      *   - old_value: 旧值
                                                      *   - new_value: 新值
                                                      */
                                                      void writeAuditLog(const std::string& key,
                                                      const std::string& old_value,
                                                      const std::string& new_value) {
                                                      // 模拟写入审计日志
                                                      // 实际实现可能写入数据库、文件或发送到审计服务
                                                      static int audit_id = 0;
                                                      audit_id++;
                                                      // 这里只是演示,实际系统会有更完整的审计记录
                                                      }
                                                      };
                                                      /**
                                                      * @brief 主函数 - 配置管理系统演示
                                                      *
                                                      * 演示观察者模式在配置管理系统中的应用,展示配置热更新和组件自动调整。
                                                      *
                                                      * @return:程序退出码
                                                      */
                                                      int main() {
                                                      std::cout << "=== 配置管理系统演示 ===" << std::endl;
                                                      // 创建配置管理器
                                                      ConfigManager config_manager;
                                                      // 创建各种系统组件
                                                      auto db_pool = std::make_shared<DatabaseConnectionPool>("主数据库");
                                                        auto log_system = std::make_shared<LogSystem>();
                                                          auto audit_system = std::make_shared<ConfigAuditSystem>();
                                                            std::cout << "\n--- 组件注册阶段 ---" << std::endl;
                                                            // 注册组件到配置管理器
                                                            config_manager.registerListener(db_pool);
                                                            config_manager.registerListener(log_system);
                                                            config_manager.registerGlobalListener(audit_system); // 审计系统监听所有变更
                                                            std::cout << "\n--- 初始配置设置 ---" << std::endl;
                                                            // 设置初始配置
                                                            config_manager.setConfig("db.max_connections", "20");
                                                            config_manager.setConfig("db.timeout", "60");
                                                            config_manager.setConfig("log.level", "INFO");
                                                            config_manager.setConfig("log.output", "file");
                                                            std::cout << config_manager.getConfigSnapshot();
                                                            std::cout << "\n--- 配置热更新演示 ---" << std::endl;
                                                            // 模拟运行时配置更新
                                                            config_manager.setConfig("db.max_connections", "50");  // 增加连接数
                                                            config_manager.setConfig("log.level", "DEBUG");        // 调整日志级别
                                                            config_manager.setConfig("app.cache_size", "1024");    // 新增配置(审计系统会记录)
                                                            std::cout << "\n--- 组件状态检查 ---" << std::endl;
                                                            // 检查组件状态
                                                            log_system->log("DEBUG", "这是一条调试消息");
                                                            log_system->log("INFO", "这是一条信息消息");
                                                            std::cout << "\n--- 批量配置更新 ---" << std::endl;
                                                            // 模拟从外部配置文件重新加载配置
                                                            config_manager.setConfig("db.max_connections", "30");
                                                            config_manager.setConfig("db.timeout", "45");
                                                            config_manager.setConfig("log.level", "WARN");
                                                            config_manager.setConfig("log.output", "console");
                                                            std::cout << "\n最终配置状态:" << std::endl;
                                                            std::cout << config_manager.getConfigSnapshot();
                                                            std::cout << "\n=== 演示完成 ===" << std::endl;
                                                            return 0;
                                                            }

4. Makefile范例

# 编译器配置
CXX := g++
CXX_STD := c++17
# 编译选项
CXXFLAGS := -std=$(CXX_STD) -Wall -Wextra -Wpedantic -O2
DEBUG_FLAGS := -g -DDEBUG -O0
RELEASE_FLAGS := -DNDEBUG -O3
# 目标文件
TARGETS := stock_system game_events config_system
# 默认构建所有目标
all: $(TARGETS)
# 股票监控系统
stock_system: stock_system.cpp
	$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) -o $@ $<
# 游戏事件系统
game_events: game_events.cpp
	$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) -o $@ $<
# 配置管理系统
config_system: config_system.cpp
	$(CXX) $(CXXFLAGS) $(RELEASE_FLAGS) -o $@ $<
# 调试版本
debug: CXXFLAGS += $(DEBUG_FLAGS)
debug: $(TARGETS)
# 清理构建文件
clean:
	rm -f $(TARGETS) *.o
# 安装依赖(Ubuntu/Debian)
install-deps:
	sudo apt-get update
	sudo apt-get install -y g++ build-essential
# 运行所有测试
test: all
	@echo "运行股票系统测试..."
	@./stock_system
	@echo
	@echo "运行游戏事件系统测试..."
	@./game_events
	@echo
	@echo "运行配置系统测试..."
	@./config_system
.PHONY: all clean debug install-deps test

5. 操作说明

5.1 编译方法

环境要求

  • GCC 7.0+ 或 Clang 5.0+
  • C++17 支持
  • Linux/Unix 系统(Windows需使用MinGW或WSL)

编译命令

# 安装编译依赖(Ubuntu/Debian)
make install-deps
# 编译所有目标
make
# 编译调试版本
make debug
# 编译并运行所有测试
make test

5.2 运行方式

股票监控系统

./stock_system

输出示例:

=== 股票价格监控系统演示 ===
--- 初始订阅阶段 ---
观察者 张投资者 开始监控股票 AAPL
观察者 李投资者 开始监控股票 AAPL
观察者 量子基金 开始监控股票 AAPL
观察者 张投资者 开始监控股票 GOOGL
观察者 量子基金 开始监控股票 GOOGL
--- 价格变化阶段 ---
股票 AAPL 价格变化: 150 -> 148.5
[张投资者] 收到通知: AAPL 当前价格 = 148.5
  → 决策: 持有 AAPL (观望中)
[李投资者] 收到通知: AAPL 当前价格 = 148.5
  → 决策: 持有 AAPL (观望中)
[量子基金] 分析报告 - AAPL: 150 → 148.5 (-1%)

游戏事件系统

./game_events

输出示例:

=== 游戏引擎事件系统演示 ===
--- 系统注册阶段 ---
注册监听器: 成就系统 -> 事件类型: 2
注册监听器: 成就系统 -> 事件类型: 0
注册监听器: 成就系统 -> 事件类型: 1
注册监听器: 统计系统 -> 事件类型: 2
注册监听器: 统计系统 -> 事件类型: 0
注册监听器: UI系统 -> 事件类型: 0
...
--- 游戏事件模拟 ---
[事件发布] 玩家 玩家1 在生成点 1 生成
[UI通知] 玩家 玩家1 在生成点 1 生成
[事件发布] 玩家 玩家2 在生成点 6 生成
[UI通知] 玩家 玩家2 在生成点 6 生成
[成就系统] 分析报告 - : 0 → 0 (+0%)

配置管理系统

./config_system

输出示例:

=== 配置管理系统演示 ===
--- 组件注册阶段 ---
注册键监听: 数据库连接池[主数据库] -> db.max_connections
注册键监听: 数据库连接池[主数据库] -> db.timeout
注册键监听: 日志系统 -> log.level
注册键监听: 日志系统 -> log.output
注册全局监听: 配置审计系统
--- 初始配置设置 ---
配置更新: db.max_connections = 20 (原值: 空)
[审计系统] 配置变更审计: db.max_connections =  -> 20
配置更新: db.timeout = 60 (原值: 空)
[审计系统] 配置变更审计: db.timeout =  -> 60
...

5.3 结果解读

正常输出特征

  • 股票系统:投资者根据价格阈值自动做出买卖决策
  • 游戏系统:各子系统协同处理游戏事件,成就自动解锁
  • 配置系统:配置变更时各组件自动调整行为

设计模式优势体现

  • 解耦性:主题和观察者相互独立,可以独立变化
  • 扩展性:新增观察者无需修改主题代码
  • 动态性:运行时可以动态添加、删除观察者关系

6. 深入解析:生命周期管理的最佳实践

6.1 weak_ptr的安全使用模式

观察者模式中最重要的技术点就是使用std::weak_ptr避免循环引用和悬空指针:

class SafeSubject {
private:
std::vector<std::weak_ptr<Observer>> observers_;
  public:
  void attach(const std::shared_ptr<Observer>& observer) {
    // 使用weak_ptr避免循环引用
    observers_.push_back(observer);
    }
    void notify() {
    // 先清理已失效的观察者
    observers_.erase(
    std::remove_if(observers_.begin(), observers_.end(),
    [](const auto& wp) { return wp.expired(); }),
    observers_.end());
    // 再通知有效的观察者
    for (auto& weak_obs : observers_) {
    if (auto observer = weak_obs.lock()) {
    observer->update();
    }
    }
    }
    };

6.2 观察者模式的变体与扩展

1. 推模型 vs 拉模型

// 推模型:主题将详细数据推送给观察者
virtual void update(const EventData& data) = 0;
// 拉模型:观察者从主题拉取需要的数据  
virtual void update(Subject* subject) = 0;

2. 事件过滤机制

class SelectiveObserver : public Observer {
private:
std::function<bool(const EventData&)> filter_;
public:
void update(const EventData& data) override {
if (filter_(data)) {
// 只处理符合条件的事件
processEvent(data);
}
}
};

3. 异步通知机制

class AsyncSubject : public Subject {
private:
std::thread notification_thread_;
public:
void asyncNotify() {
notification_thread_ = std::thread([this]() {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
notify();  // 在后台线程通知
});
}
};

7. 总结

观察者模式是构建松耦合、可扩展系统的利器。通过本文的三个完整案例,我们深入掌握了:

核心价值

  • 实现主题与观察者的解耦,提高代码的可维护性
  • 支持广播通信,简化一对多的依赖关系管理
  • 提供动态订阅机制,增强系统灵活性

关键技术

  • 使用std::weak_ptr安全管理观察者生命周期
  • 通过模板和继承支持多种事件类型
  • 实现高效的通知和清理机制

适用场景

  • 事件驱动架构:GUI系统、游戏引擎
  • 数据监控系统:股票行情、系统监控
  • 配置管理系统:热更新、动态调整
  • 分布式系统:消息队列、发布订阅

观察者模式虽然简单,但却是构建现代软件系统的基础模式。掌握它,就掌握了构建响应式、可扩展系统的关键技能。

posted @ 2025-10-03 21:15  yxysuanfa  阅读(24)  评论(0)    收藏  举报