[デザインパターン] ヘッドファーストデザインパターン - オブザーバーパターン C++実装

デザイン パターンの最大の役割は、変更と安定性の間の分離点を見つけて、それらを分離して変更を管理することです。ウサギのように小銭をケージに閉じ込め、飛び出して部屋全体を汚すことなく、ケージ内で飛び回らせます。

デザイン思考

トピック オブジェクト (パブリッシャー) は一部のデータを管理し、トピック内のデータが変更されるとオブザーバー (サブスクライバー) に通知されます。

Observer パターンは、オブジェクト間の 1 対多の依存関係を定義します。オブジェクトの状態が変化すると、そのすべての依存関係が自動的に通知され、更新されます。これにより、複数のオブジェクトで同じデータを制御するよりもすっきりした OO 設計が実現します。

ビジネスシーン

現在気象観測所クラスがあると仮定すると、この気象観測所クラスは気温、湿度、気圧の最新データを随時更新します。これらの値が変化した場合は、表示のために直ちに一部の気象局に通知する必要があります。 、取得するデータは同じですが、図表を使ったり、テキストを使ったり、音声放送などを使ってデザインコードを与えるなど、表示方法が異なる場合があります。

コード例

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 观察者抽象类
class Observer
{
public:
    virtual void update(const float tmp, const float hum, const float pre) = 0;
    virtual ~Observer() {}
};

// 展示抽象类
class Display
{
public:
    virtual void display() const = 0;
    virtual ~Display() {}
};

// 主题抽象类
class Subject
{
public:
    virtual void registerObserver(Observer* b) = 0;
    virtual void removeObserver(Observer* b)   = 0;
    virtual void notifyObserver() const        = 0;
    virtual ~Subject() {}
};

class WeatherData : public Subject
{
private:
    std::vector<Observer*> observers;
    float                  temperature = 0;
    float                  humidity    = 0;
    float                  pressure    = 0;

public:
    WeatherData() : Subject() {}

    void registerObserver(Observer* b)
    {
        observers.push_back(b);
    }

    void removeObserver(Observer* ob)
    {
        auto it = find(observers.begin(), observers.end(), ob);
        if (it != observers.end())
        {
            observers.erase(it);
        }
    }
    // 通知观察者,使得所有观察者更新信息。
    void notifyObserver() const
    {
        for (auto& it : observers)
        {
            it->update(temperature, humidity, pressure);
        }
    }

    void measurementsChanged()
    {
        notifyObserver();
    }

    // 设置气象站天气信息并通知观察者。
    void setMeasurements(const float tmp, const float hum, const float pre)
    {
        temperature = tmp;
        humidity    = hum;
        pressure    = pre;
        measurementsChanged();
    }

    ~WeatherData()
    {
        for (auto& each : observers)
        {
            delete each;
            each = nullptr;
        }
    }
};

class CurrentConditionsDisplay : public Observer, public Display
{
private:
    float    temperature = 0;
    float    humidity    = 0;
    Subject* weatherData = nullptr;

public:
    // 初始化信息板,并在气象站对其登记。
    CurrentConditionsDisplay(Subject* wd) : Observer(), Display()
    {
        weatherData = wd;
        weatherData->registerObserver(this);
    }
    // 更新天气信息并展示。
    void update(const float tmp, const float hum, const float pre)
    {
        temperature = tmp;
        humidity    = hum;
        display();
    }

    void display() const
    {
        cout << "气象局1: 当前温度:" << temperature << ", 当前湿度:" << humidity << endl;
    }

    ~CurrentConditionsDisplay()
    {
        if (weatherData)
        {
            delete weatherData;
            weatherData = nullptr;
        }
    }
};

class CurrentConditionsDisplay2 : public Observer, public Display
{
private:
    float    temperature = 0;
    float    humidity    = 0;
    Subject* weatherData = nullptr;

public:
    // 初始化信息板,并在气象站对其登记。
    CurrentConditionsDisplay2(Subject* wd) : Observer(), Display()
    {
        weatherData = wd;
        weatherData->registerObserver(this);
    }
    // 更新天气信息并展示。
    void update(const float tmp, const float hum, const float pre)
    {
        temperature = tmp;
        humidity    = hum;
        display();
    }

    void display() const
    {
        cout << "气象局2: 当前温度:" << temperature << ", 当前湿度:" << humidity << endl;
    }

    ~CurrentConditionsDisplay2()
    {
        if (weatherData)
        {
            delete weatherData;
            weatherData = nullptr;
        }
    }
};

int main()
{
    WeatherData*               wd  = new WeatherData();
    CurrentConditionsDisplay*  cd  = new CurrentConditionsDisplay(wd);
    CurrentConditionsDisplay2* cd2 = new CurrentConditionsDisplay2(wd);

    // wd修改天气信息 并通知展示板
    wd->setMeasurements(80, 65, 30.4f);
    wd->setMeasurements(60, 35, 32.1f);
    wd->removeObserver(cd);
    cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl;
    wd->setMeasurements(60, 35, 31.1f);

    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_43717839/article/details/132540328