观察者模式定义

观察者模式是一种行为型设计模式,用于在对象之间建立一对多依赖关系。当一个对象(称为Subject,主题)的状态发生改变时,所有依赖它的对象(称为Observer,观察者)会自动收到通知并更新。该模式的核心是解耦主题与观察者,避免直接依赖。

适用场景

1.​事件驱动系统:

  • 如用户界面按钮点击事件、游戏中的成就系统。

2.状态同步需求:

  • 例如天气预报系统通知多个显示设备更新数据。

3.​跨模块通信:

  • 订单状态变化时通知库存系统、支付系统等。

4.避免轮询检查:

  • 用推送机制代替观察者主动轮询主题状态。

代码示例

未使用观察者模式的代码

以下是一个简单的温度监控系统,直接硬编码通知逻辑:

#include <iostream>
#include <vector>

// 温度传感器(主题)
class TemperatureSensor {
private:
    float temperature;
    std::vector<class Display*> displays; // 硬编码依赖具体显示设备

public:
    void setTemperature(float temp) {
        temperature = temp;
        // 直接调用所有显示设备的更新方法
        for (auto display : displays) {
            display->update(temperature);
        }
    }

    void addDisplay(Display* display) {
        displays.push_back(display);
    }
};

// 显示设备(观察者)
class Display {
public:
    void update(float temp) {
        std::cout << "当前温度: " << temp << "°C" << std::endl;
    }
};

int main() {
    TemperatureSensor sensor;
    Display display1, display2;

    sensor.addDisplay(&display1);
    sensor.addDisplay(&display2);

    sensor.setTemperature(25.5); // 输出两次温度信息
    return 0;
}

使用观察者模式优化

通过抽象接口和动态注册机制解耦主题与观察者:

#include <iostream>
#include <vector>
#include <memory>

// 观察者接口(抽象层)
class IObserver {
public:
    virtual ~IObserver() = default;
    virtual void update(float temperature) = 0; // 统一更新方法
};

// 主题接口(抽象层)
class ISubject {
public:
    virtual ~ISubject() = default;
    virtual void registerObserver(std::shared_ptr<IObserver> observer) = 0;
    virtual void notifyObservers() = 0;
};

// 具体主题:温度传感器
class TemperatureSensor : public ISubject {
private:
    float temperature;
    std::vector<std::shared_ptr<IObserver>> observers; // 观察者列表

public:
    void setTemperature(float temp) {
        temperature = temp;
        notifyObservers(); // 通知所有观察者
    }

    void registerObserver(std::shared_ptr<IObserver> observer) override {
        observers.push_back(observer);
    }

    void notifyObservers() override {
        for (auto& observer : observers) {
            observer->update(temperature);
        }
    }
};

// 具体观察者:显示屏
class Display : public IObserver {
public:
    void update(float temperature) override {
        std::cout << "显示屏更新 -> 温度: " << temperature << "°C" << std::endl;
    }
};

// 具体观察者:手机通知(新增观察者类型)
class PhoneNotification : public IObserver {
public:
    void update(float temperature) override {
        std::cout << "手机通知: 当前温度 " << temperature << "°C" << std::endl;
    }
};

int main() {
    // 创建主题和观察者
    auto sensor = std::make_shared<TemperatureSensor>();
    auto display = std::make_shared<Display>();
    auto phone = std::make_shared<PhoneNotification>();

    // 注册观察者
    sensor->registerObserver(display);
    sensor->registerObserver(phone);

    // 温度变化触发通知
    sensor->setTemperature(25.5);
    /* 输出:
        显示屏更新 -> 温度: 25.5°C
        手机通知: 当前温度 25.5°C
    */

    return 0;
}

代码注释:

IObserver 接口:定义统一的 update 方法,所有观察者必须实现。
ISubject 接口:提供注册和通知观察者的方法,主题类(如 TemperatureSensor)实现该接口。
​动态注册机制:通过 registerObserver 动态添加观察者,无需修改主题代码。
​解耦设计:主题仅依赖 IObserver 接口,不关心具体观察者类型。

模式优势

​松耦合:主题和观察者通过接口交互,互不依赖具体实现。
​扩展性:新增观察者类型无需修改主题代码(如添加 EmailNotification)。
​事件驱动:支持广播通知,避免轮询资源浪费。
​符合开闭原则:主题和观察者可以独立扩展。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐