一.概念

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