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

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

1. 背景与核心概念

1.1 设计模式的起源与发展

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

时期 主要贡献 应用场景 技术特点
1970s Smalltalk MVC框架 GUI应用程序 模型-视图分离
1994 GoF《设计模式》 事件处理系统 标准化模式描述
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 生命周期管理的挑战

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

cpp 复制代码
// 危险代码示例:悬空指针问题
Subject* subject = new Subject();
Observer* observer = new ConcreteObserver();

subject->attach(observer);  // 主题持有观察者指针

// 之后某个时刻...
delete observer;  // 观察者被销毁
// 但主题仍然持有已销毁对象的指针!

subject->notify();  // 灾难:访问已释放内存

解决方案对比

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

2.3 性能与扩展性权衡

通知性能考量

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

扩展性设计

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

3. 实例与应用场景

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

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

cpp 复制代码
#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.0 attach(张投资者) attach(李投资者) attach(量子基金) setPrice(148.5) update() update() update() 所有观察者收到价格下跌通知 setPrice(142.0) update() update() update() detach(李投资者) setPrice(158.0) update() update() 李投资者已取消订阅,不再接收通知 AppleStock 张投资者 李投资者 量子基金

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

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

cpp 复制代码
#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 案例三:配置管理系统

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

cpp 复制代码
#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范例

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)

编译命令

bash 复制代码
# 安装编译依赖(Ubuntu/Debian)
make install-deps

# 编译所有目标
make

# 编译调试版本
make debug

# 编译并运行所有测试
make test

5.2 运行方式

股票监控系统

bash 复制代码
./stock_system

输出示例:

复制代码
=== 股票价格监控系统演示 ===

--- 初始订阅阶段 ---
观察者 张投资者 开始监控股票 AAPL
观察者 李投资者 开始监控股票 AAPL
观察者 量子基金 开始监控股票 AAPL
观察者 张投资者 开始监控股票 GOOGL
观察者 量子基金 开始监控股票 GOOGL

--- 价格变化阶段 ---
股票 AAPL 价格变化: 150 -> 148.5
[张投资者] 收到通知: AAPL 当前价格 = 148.5
  → 决策: 持有 AAPL (观望中)
[李投资者] 收到通知: AAPL 当前价格 = 148.5
  → 决策: 持有 AAPL (观望中)
[量子基金] 分析报告 - AAPL: 150 → 148.5 (-1%)

游戏事件系统

bash 复制代码
./game_events

输出示例:

复制代码
=== 游戏引擎事件系统演示 ===

--- 系统注册阶段 ---
注册监听器: 成就系统 -> 事件类型: 2
注册监听器: 成就系统 -> 事件类型: 0
注册监听器: 成就系统 -> 事件类型: 1
注册监听器: 统计系统 -> 事件类型: 2
注册监听器: 统计系统 -> 事件类型: 0
注册监听器: UI系统 -> 事件类型: 0
...

--- 游戏事件模拟 ---
[事件发布] 玩家 玩家1 在生成点 1 生成
[UI通知] 玩家 玩家1 在生成点 1 生成
[事件发布] 玩家 玩家2 在生成点 6 生成
[UI通知] 玩家 玩家2 在生成点 6 生成
[成就系统] 分析报告 - : 0 → 0 (+0%)

配置管理系统

bash 复制代码
./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避免循环引用和悬空指针:

cpp 复制代码
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 拉模型

cpp 复制代码
// 推模型:主题将详细数据推送给观察者
virtual void update(const EventData& data) = 0;

// 拉模型:观察者从主题拉取需要的数据  
virtual void update(Subject* subject) = 0;

2. 事件过滤机制

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

3. 异步通知机制

cpp 复制代码
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系统、游戏引擎
  • 数据监控系统:股票行情、系统监控
  • 配置管理系统:热更新、动态调整
  • 分布式系统:消息队列、发布订阅

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

相关推荐
奔跑吧邓邓子3 小时前
【C++实战(62)】从0到1:C++打造TCP网络通信实战指南
c++·tcp/ip·实战·tcp·网络通信
努力学习的小廉4 小时前
我爱学算法之—— 分治-快排
c++·算法
charlie1145141914 小时前
精读C++20设计模式——行为型设计模式:命令模式
c++·学习·设计模式·程序设计·命令模式·c++20
AA陈超4 小时前
虚幻引擎UE5专用服务器游戏开发-32 使用Gameplay Tags阻止连招触发
c++·游戏·ue5·游戏引擎·虚幻
金色熊族5 小时前
ubuntu20.04编译qt源码5.15.3
linux·c++·qt
智能化咨询5 小时前
【C++】异常介绍:高级应用与性能优化
c++
呆瑜nuage6 小时前
c++之AVL树
c++
星空寻流年6 小时前
设计模式第六章(观察者模式)
网络·观察者模式·设计模式
磨十三7 小时前
C++ 类型转换全面解析:从 C 风格到 C++ 风格
java·c语言·c++