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
相关推荐
liuyao_xianhui7 小时前
优选算法_位运算_只出现一次的数字3_C++
开发语言·数据结构·c++·算法·leetcode·链表·动态规划
十五年专注C++开发7 小时前
Linux 下用 VS Code 高效调试
linux·运维·服务器·c++·vscode
郝学胜-神的一滴7 小时前
贪心策略实战Leetcode 860题:柠檬水找零问题的优雅解法
数据结构·c++·算法·leetcode·职场和发展
茉莉玫瑰花茶7 小时前
CMake 工程指南 - 工程场景(4)
服务器·c++·cmake
Sunsets_Red7 小时前
乘法逆元的 exgcd 求法
c++·学习·数学·算法·c#·密码学·信息学竞赛
米啦啦.7 小时前
函数模板,namespace名字空间,动态内存管理,C++11新特性,
c++·动态内存管理·函数模板·c++新特性·名字空间
茉莉玫瑰花茶8 小时前
CMake 工程指南 - 工程场景(5)
开发语言·c++·cmake
handler018 小时前
算法:字符串哈希
c语言·数据结构·c++·笔记·算法·哈希算法·散列表
szm02258 小时前
设计模式-
设计模式
handler018 小时前
算法:查并集
开发语言·数据结构·c++·笔记·学习·算法·c