设计模式 观察者模式

目录

观察者模式详解

[1. 定义](#1. 定义)

[2. 应用场景](#2. 应用场景)

具体应用示例

[3. 代码结构实现](#3. 代码结构实现)

观察者接口(抽象基类)

具体观察者类(继承自观察者接口)

被观察者(主题)类

客户端使用


观察者模式详解

1. 定义

观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象间的一种一对多的依赖关系,使得每当"一"方(被观察者/主题)的状态发生改变时,所有依赖它的"多"方(观察者)都会自动收到通知并被更新。这种模式也被称为发布-订阅模式(Publish-Subscribe Pattern)。

关键特征:

  • 松耦合:被观察者不需要知道具体的观察者类,只需维护一个观察者接口的列表
  • 动态订阅:观察者可以在运行时注册和取消注册
  • 自动通知:状态变化时自动通知所有注册的观察者

2. 应用场景

观察者模式适用于以下典型场景:

  1. "一"对"多"的依赖关系:当一个对象的改变需要同时改变其他多个对象时
  2. 事件驱动系统:如GUI系统中的事件处理、游戏中的成就系统等
  3. 数据监控系统:如数据变化时更新多个显示设备

具体应用示例

以数据中心和显示设备为例:

  • 被观察者(Subject):数据中心,负责存储核心数据
  • 观察者(Observers):多种显示设备(如LCD显示器、LED大屏、移动设备等),需要实时反映数据变化

3. 代码结构实现

观察者接口(抽象基类)

cpp 复制代码
class Observer {
public:
    virtual ~Observer() = default;
    virtual void update(float temperature, float humidity, float pressure) = 0;
};

具体观察者类(继承自观察者接口)

cpp 复制代码
// LCD显示设备
class LCDDisplay : public Observer {
public:
    void update(float temp, float humidity, float pressure) override {
        // 实现具体的LCD显示更新逻辑
        std::cout << "LCD Display updated - Temp: " << temp 
                  << ", Humidity: " << humidity 
                  << ", Pressure: " << pressure << std::endl;
    }
};

// LED大屏显示
class LEDDisplay : public Observer {
public:
    void update(float temp, float humidity, float pressure) override {
        // 实现LED大屏的显示更新逻辑
        std::cout << "LED Display updated - Temp: " << temp 
                  << ", Humidity: " << humidity 
                  << ", Pressure: " << pressure << std::endl;
    }
};

被观察者(主题)类

cpp 复制代码
class WeatherData {
private:
    std::vector<Observer*> observers;  // 观察者容器
    float temperature;
    float humidity;
    float pressure;

public:
    void registerObserver(Observer* o) {
        observers.push_back(o);
    }

    void removeObserver(Observer* o) {
        // 从容器中移除观察者
        observers.erase(std::remove(observers.begin(), observers.end(), o), observers.end());
    }

    void notifyObservers() {
        for (auto observer : observers) {
            observer->update(temperature, humidity, pressure);
        }
    }

    void measurementsChanged() {
        notifyObservers();  // 数据变化时通知所有观察者
    }

    void setMeasurements(float temp, float humidity, float pressure) {
        this->temperature = temp;
        this->humidity = humidity;
        this->pressure = pressure;
        measurementsChanged();
    }
};

客户端使用

cpp 复制代码
int main() {
    WeatherData weatherData;  // 被观察者
    
    // 创建具体观察者
    LCDDisplay lcdDisplay;
    LEDDisplay ledDisplay;
    
    // 注册观察者
    weatherData.registerObserver(&lcdDisplay);
    weatherData.registerObserver(&ledDisplay);
    
    // 模拟数据变化
    weatherData.setMeasurements(25.5, 65, 1013.2);
    weatherData.setMeasurements(26.0, 70, 1012.8);
    
    // 移除一个观察者
    weatherData.removeObserver(&ledDisplay);
    weatherData.setMeasurements(27.5, 68, 1014.0);
    
    return 0;
}

这个实现展示了观察者模式的核心思想:当气象数据(被观察者)发生变化时,所有注册的显示设备(观察者)都会自动更新显示内容,且可以动态添加或移除观察者。

cpp 复制代码
class IDisplay
{
public:
	virtual void show(float temprature) = 0;
	virtual ~IDisplay() {}
};
cpp 复制代码
class DisplayA : public IDisplay
{
public:
	virtual void show(float temprature)
	{
		std::cout << "DisplayA Show" << std::endl;
	}
};
class DisplayB : public IDisplay
{
public:
	virtual void show(float temprature)
	{
		std::cout << "DisplayB Show" << std::endl;
	}
};
cpp 复制代码
class DateCenter
{
public:
	void Attach(IDisplay* ob)
	{
	}
	void Detach(IDisplay* ob)
	{
	}
	void Notify()
	{
		double d = 1.0;
		for (auto& ob : obs)
		{
			ob->show(d);
		}
	}
private:
	std::list<IDisplay*> obs;
};
cpp 复制代码
int main()
{
	DateCenter* DC = new DateCenter();

	IDisplay* Da = new DisplayA();
	DC->Attach(Da);
	IDisplay* Db = new DisplayB();
	DC->Attach(Db);

	// DC 发生变化
	DC->Notify();
}