c++设计模式-观察者模式

一.概念

观察者设计模式属于行为型设计模式 ,又称发布-订阅 模式,定义了对象间的一对多依赖关系,被观察对象 状态发生变化时,所有订阅它的观察对象都会受到通知并自动更新。

二.原理

1.Subject(被观察者)

包含观察者对象的集合,提供增加、删除、通知观察者对象的抽象接口。

2.ConcreteSubject(具体的被观察者)

Subject抽象类接口的具体实现,维护观察者列表,并将变化通知所有观察者。

3.Observer(观察者)

接收Subject通知的对象,订阅Subject的状态,并提供更新操作的统一抽象接口。

4.ConcreteObserver(具体的观察者)

Observer抽象类接口的具体实现,提供了更新操作的具体实现,收到subject通知后进行更新操作。

三.特点

1.优势

  • 符合开闭原则的要求。
  • 支持广播的通信方式。
  • 动态添加观察者,代码扩展性好。

2.劣势

  • 每次状态变化都要遍历所有观察者,性能开销大。
  • 每次状态变化都要通知所有观察者,通信时间长。
  • 观察者数量过多使代码的可读性变差。

四.代码实现

1.demo1-传参通知

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
//抽象类
class Observer {
public:
    virtual void update(int data) = 0;//纯虚函数
};

class ConcreteObserver: public Observer{
public:
    ConcreteObserver(string name)
    {
        m_sName = name;
    }

    void update(int data)
    {
        cout << m_sName << " received data:" << data << endl;
    }

private:
    string m_sName;
};

class Subject {
public:
    virtual void attach(Observer *observer) = 0;
    virtual void detach(Observer *observer) = 0;
    virtual void notify(int data) = 0;
};

class ConcreteSubject :public Subject{
public:
    void attach(Observer *observer)
    {
        observers.push_back(observer);
    }

    void detach(Observer *observer)
    {
        for(auto it=observers.begin();it!=observers.end();it++)
        {
            if(*it == observer)
            {
                observers.erase(it);
                break;
            }
        }
    }

    void notify(int data)
    {
        for(auto it=observers.begin();it!=observers.end();it++)
        {
            (*it)->update(data);
        }
    }

private:
    vector<Observer*> observers;
};

int main() {
    cout << "observer demo1!" << endl;
    ConcreteObserver observer1("observer1");
    ConcreteObserver observer2("observer2");
    ConcreteObserver observer3("observer3");

    ConcreteSubject subject;
    subject.attach(&observer1);
    subject.attach(&observer2);
    subject.attach(&observer3);
    subject.notify(10);

    subject.detach(&observer1);
    subject.notify(20);

    return 0;
}

2.demo2-模拟天气预报

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

class Observer{
public:
    virtual void update(float temperature,float humidity,float pressure) = 0;
};

class Display:public Observer{
public:
    void update(float temperature,float humidity,float pressure){
        cout << "Temperature:" << temperature << "℃, Humidity:" << humidity << "%, Pressure:" << pressure << "hPa" << endl;
    }
};

class WeatherStation{
private:
    float m_fTemperature;
    float m_fHumidity;
    float m_fPressure;
    vector<Observer*> m_vObservers;

public:
    void attach(Observer* observer){
        m_vObservers.push_back(observer);
    }

    void detach(Observer* observer){
        for(auto it=m_vObservers.begin();it!=m_vObservers.end();it++)
        {
            if(*it == observer)
            {
                m_vObservers.erase(it);
                break;
            }
        }
    }

    void notify(){
        for(auto it=m_vObservers.begin();it!=m_vObservers.end();it++){
            (*it)->update(m_fTemperature,m_fHumidity,m_fPressure);
        }
    }

    void setValue(float temp,float hum,float press){
        m_fTemperature = temp;
        m_fHumidity = hum;
        m_fPressure = press;
        notify();
    }
};

int main() {
    std::cout << "observer demo2!" << std::endl;

    WeatherStation weatherStation;
    Display display1;
    Display display2;
    weatherStation.attach(&display1);
    weatherStation.attach(&display2);
    weatherStation.setValue(25.5,50,103);
    weatherStation.setValue(25.7,60,152);

    return 0;
}

五.运行结果

1.demo1-传参通知

bash 复制代码
observer demo1!
observer1 received data:10
observer2 received data:10
observer3 received data:10
observer2 received data:20
observer3 received data:20

2.demo2-模拟天气预报

bash 复制代码
observer demo2!
Temperature:25.5℃, Humidity:50%, Pressure:103hPa
Temperature:25.5℃, Humidity:50%, Pressure:103hPa
Temperature:25.7℃, Humidity:60%, Pressure:152hPa
Temperature:25.7℃, Humidity:60%, Pressure:152hPa
相关推荐
炸膛坦客3 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
旖-旎3 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
Henry Zhu1234 小时前
C++中的特殊成员函数与智能指针
c++
_wyt0016 小时前
多重背包问题详解
c++·背包dp
Ljwuhe7 小时前
C++——多态
开发语言·c++
越甲八千8 小时前
STL stack为何没有迭代器
c++
从零开始的代码生活_9 小时前
C++ 继承详解:访问控制、对象模型、菱形继承与设计取舍
开发语言·c++·后端·学习·算法
云小逸9 小时前
【C++ 第七阶段:模板、泛型编程与工程综合详解】
开发语言·c++
GIS阵地10 小时前
QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)
开发语言·前端·c++·qt·qgis
王维同学10 小时前
[原创][Windows C++]LSA 认证、安全与通知包的注册表枚举
c++·windows·安全