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
相关推荐
Trouvaille ~9 小时前
【Linux】UDP Socket编程实战(三):多线程聊天室与线程安全
linux·服务器·网络·c++·安全·udp·socket
jiang_changsheng10 小时前
MCP协议的核心架构基础
c语言·开发语言·c++·python·comfyui
永远睡不够的入10 小时前
类和对象(下):流重载、初始化列表、友元
c++
忧郁的Mr.Li10 小时前
设计模式--单例模式
javascript·单例模式·设计模式
范纹杉想快点毕业10 小时前
状态机设计模式与嵌入式系统开发完整指南
java·开发语言·网络·数据库·mongodb·设计模式·架构
Trouvaille ~10 小时前
【Linux】UDP Socket编程实战(四):地址转换函数深度解析
linux·服务器·网络·c++·udp·socket·地址转换函数
王老师青少年编程10 小时前
2022信奥赛C++提高组csp-s复赛真题及题解:星战
c++·真题·csp·信奥赛·csp-s·提高组·星战
兩尛10 小时前
2. 两数相加 c++
开发语言·c++
j4455661110 小时前
C++中的备忘录模式
开发语言·c++·算法
近津薪荼11 小时前
dfs专题——二叉树的深搜3(二叉树剪枝)
c++·学习·算法·深度优先