观察者模式 (Observer Pattern)

观察者模式 (Observer Pattern)

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

基础组件
  • Subject (主题):被观察的对象,维护观察者列表
  • Observer (观察者):定义更新接口
  • ConcreteSubject (具体主题):存储状态,状态改变时通知观察者
  • ConcreteObserver (具体观察者):实现更新接口
继承/实现关系
Subject <|-- ConcreteSubject
Observer <|-- ConcreteObserver
ConcreteSubject --> Observer (通知观察者)
应用场景
  • 需要将对象状态变化通知给其他对象
  • 一个对象改变需要改变其他对象,但不知道具体有多少对象需要改变
  • 跨系统事件通知
C++ 实现(气象站数据发布)
#include <iostream>
#include <memory>
#include <string>
#include <vector>

/*
* 观察者模式
* 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
* 基础组件:
* - Subject (主题):被观察的对象,维护观察者列表
* - Observer (观察者):定义更新接口
* - ConcreteSubject (具体主题):存储状态,状态改变时通知观察者
* - ConcreteObserver (具体观察者):实现更新接口
* 继承/实现关系:
* ConcreteSubject 继承自 Subject,ConcreteObserver 实现 Observer 接口。
* ConcreteSubject 维护一个观察者列表,并在状态改变时调用每个观察者的更新方法。
*/

// 观察者接口
class Observer {
public:
    virtual ~Observer() = default;
    virtual void update(float temperature, float humidity) = 0;
};

// 主题接口
class Subject {
public:
    virtual void registerObserver(std::shared_ptr<Observer> o) = 0;
    virtual void removeObserver(std::shared_ptr<Observer> o) = 0;
    virtual void notifyObservers() = 0;
};

// 具体主题:气象站,提供注册、移除观察者和通知观察者的功能
class WeatherStation : public Subject {
public:
    void registerObserver(std::shared_ptr<Observer> o) override {
        observers_.push_back(o);
    }

    void removeObserver(std::shared_ptr<Observer> o) override {
        auto it = std::find(observers_.begin(), observers_.end(), o);
        if (it != observers_.end()) {
            observers_.erase(it);
        }
    }

    void notifyObservers() override {
		// 具体主题负责通知所有注册的观察者
        for (auto& o : observers_) {
            o->update(temperature_, humidity_);
        }
    }

    // 气象数据更新时调用
    void setMeasurements(float temperature, float humidity) {
        temperature_ = temperature;
        humidity_ = humidity;
        
		// 通知所有观察者
        notifyObservers();
    }

private:
    std::vector<std::shared_ptr<Observer>> observers_;
    float temperature_ = 0.0f;
    float humidity_ = 0.0f;
};

// 具体观察者:显示当前天气,提供一个update方法来接收主题的状态更新
class CurrentConditionsDisplay : public Observer {
public:
    void update(float temperature, float humidity) override {
        temperature_ = temperature;
        humidity_ = humidity;
        display();
    }

    void display() const {
        std::cout << "Current conditions: " << temperature_
            << "°C and " << humidity_ << "% humidity\n";
    }

private:
    float temperature_;
    float humidity_;
};

// 具体观察者:天气统计
class StatisticsDisplay : public Observer {
public:
    void update(float temperature, float humidity) override {
        // 更新统计信息(这里简化)
        maxTemp_ = std::max(maxTemp_, temperature);
        minTemp_ = std::min(minTemp_, temperature);
        display();
    }

    void display() const {
        std::cout << "Weather stats: Max=" << maxTemp_
            << "°C, Min=" << minTemp_ << "°C\n";
    }

private:
    float maxTemp_ = -100.0f;
    float minTemp_ = 100.0f;
};


void ObserverPattern()
{
	std::cout << std::string(13, '-') << " Observer Pattern " << std::string(13, '-') << std::endl;

    auto weatherStation = std::make_shared<WeatherStation>();

    auto currentDisplay = std::make_shared<CurrentConditionsDisplay>();
    auto statsDisplay = std::make_shared<StatisticsDisplay>();

    weatherStation->registerObserver(currentDisplay);
    weatherStation->registerObserver(statsDisplay);

    // 更新气象数据
    weatherStation->setMeasurements(25.0f, 65.0f);
    weatherStation->setMeasurements(27.5f, 70.0f);
    weatherStation->setMeasurements(26.8f, 80.0f);

    // 移除一个观察者
    weatherStation->removeObserver(statsDisplay);
    weatherStation->setMeasurements(22.3f, 75.0f);
}
组件对应关系
  • Subject → 主题接口
  • WeatherStation → 具体主题
  • Observer → 观察者接口
  • CurrentConditionsDisplay/StatisticsDisplay → 具体观察者
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值