C++观察者模式:Observer Pattern

案例:开发一个天气检测的APP,当天气信息发生变化时,把信息实时更新到布告板上。利用WeatherData对象获取数据并更新到各个布告板上。

出版者 + 订阅者 = 观察者模式;

当出版者出版新的报纸时自动给订阅了报纸的订阅者发送信息。

出版者改称为“主题”(Subject)

订阅者改称为“观察者”(Observer)

后续新增的观察者可以通过注册成为主题对象的观察者,也可以通过操作使自己不再是该主题对象的观察者。

观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

设计原则:为了交互对象之间的松耦合设计而努力。

主题对象和观察者之间就采用松耦合方式结合。主题对象不知道观察者的细节,只知道观察者实现了主题对象接口。

类图:

注:另外一种实现为把getTemperature() 和 getHumidity() 放在WeatherData类中,update()函数的参数为(int temperature, int humidity);

本实现是把整个Subject对象作为参数传入给update()函数,方便后续的扩展,不限制update()函数参数成员类型;

指针:聚合关系

成员:组合关系

setMeasurements() -> measurementChanged() -> notifyObserver() -> update() -> display();

实现如下:

subject.h:

#ifndef SUBJECT_H
#define SUBJECT_H
#include "observer.h"


class Subject {
public:
    virtual void registerObserver(Observer* o) = 0;
    virtual void removeObserver(Observer* o) = 0;
    virtual void notifyObserver() = 0;
    virtual int getTemperature() = 0;
    virtual int getHumidity() = 0;
};

#endif // SUBJECT_H

weatherData.h:

#ifndef WEATHERDATA_H
#define WEATHERDATA_H
#include <vector>
#include "subject.h"


class WeatherData : public Subject {
public:
    virtual void registerObserver(Observer* o) override;
    virtual void removeObserver(Observer* o) override;
    virtual void notifyObserver() override;

    virtual int getTemperature() override;
    virtual int getHumidity() override;
    void setMeasurements(int temperature, int humidity);
    void measurementsChanged();

private:
    vector<Observer*> m_observersV; // 0规则
    int m_temperature;
    int m_humidity;
};

// 注册
void WeatherData::registerObserver(Observer* o)
{
    m_observersV.push_back(o);
}

// 删除
void WeatherData::removeObserver(Observer* o)
{
    vector<Observer*>::iterator itr = m_observersV.begin();
    while (itr != m_observersV.end()) {
        if(*itr == o)
        {
            itr = m_observersV.erase(itr);
        }
        else
        {
            itr ++;
        }
    }
}

// 通知观察者
void WeatherData::notifyObserver()
{
    for(int i = 0; i < m_observersV.size(); i++)
    {
        Observer* obs = (Observer*)m_observersV[i];
        obs->update((Subject*) this);
    }
}


void WeatherData::measurementsChanged()
{
    notifyObserver();
}

void WeatherData::setMeasurements(int temperature, int humidity)
{
    m_temperature = temperature;
    m_humidity = humidity;
    measurementsChanged();
}


int WeatherData::getHumidity()
{
    return this->m_humidity;
}

int WeatherData::getTemperature()
{
    return this->m_temperature;
}

#endif // WEATHERDATA_H

observer.h:

#ifndef OBSERVER_H
#define OBSERVER_H
#include <iostream>
using namespace std;

class Subject;
class Observer {
public:
    virtual void update(Subject* subject) = 0;
};

#endif // OBSERVER_H

display.h:

#ifndef DISPLAY_H
#define DISPLAY_H
#include <iostream>
using namespace std;

class Display {
public:
    virtual void display() = 0;
};
#endif // DISPLAY_H

temDisplay.h:

#ifndef TEMDISPLAY_H
#define TEMDISPLAY_H
#include "subject.h"
#include "display.h"

class TemDisplay : public Observer, public Display{
public:
    TemDisplay(Subject* weatherData);
    virtual void update(Subject* subject) override; // 传递一个指针不用指定特定的元素
    virtual void display() override;
private:

    Subject* m_weatherData; // 构造需要weather对象,方便后续的取消注册
    int m_temperature;
};

TemDisplay::TemDisplay(Subject* weatherData)
{
    m_weatherData = weatherData;
}

void TemDisplay::display()
{
    cout << "当前温度为 " << m_weatherData->getTemperature() << " 度" << endl;
}

void TemDisplay::update(Subject* subject)
{
    m_weatherData = subject;
    cout << "温度显示器更新: ";
    display();
}


#endif // TEMDISPLAY_H

humDisplay.h:

#ifndef HUMDISPLAY_H
#define HUMDISPLAY_H
#include "subject.h"
#include "display.h"

class HumDisplay : public Observer, public Display{
public:
    HumDisplay(Subject* weatherData);
    virtual void update(Subject* subject) override; // 传递一个指针不用指定特定的元素
    virtual void display() override;
private:

    Subject* m_weatherData; // 构造需要weather对象,方便后续的取消注册
    int m_humidity;
};

HumDisplay::HumDisplay(Subject* weatherData)
{
    m_weatherData = weatherData;
}

void HumDisplay::display()
{
    cout << "当前湿度为 " << m_weatherData->getHumidity() << " %" << endl;
}

void HumDisplay::update(Subject* subject)
{
    m_weatherData = subject;
    cout << "湿度显示器更新: ";
    display();
}
#endif // HUMDISPLAY_H

main.h:

/*
 * 观察者模式
 *
 * date:2023-9-7
*/

#include "weatherData.h"
#include "temDisplay.h"
#include "humDisplay.h"

int main()
{
    WeatherData* weatherData = new WeatherData();
    Observer* temDisplay = new TemDisplay(weatherData);
    Observer* humDisplay = new HumDisplay(weatherData);

    weatherData->registerObserver(temDisplay);
    weatherData->registerObserver(humDisplay);

    weatherData->setMeasurements(20, 40);
    puts("");

    cout << "取消注册湿度显示器观察者\n" <<endl;

    weatherData->removeObserver(humDisplay);

    weatherData->setMeasurements(30, 30);

}

运行结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值