观察者模式: 出版者+订阅者
主题对象(出版者)管理某些数据,当主题内的数据改变,就会通知观察者(订阅者)。
观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。相比让多个对象控制同一份数据,可以得到更干净的OO设计。
设计原则:
为了交互对象之间的松耦合努力。
改变一方都不会影响另一方。两者松耦合,但他们仍然可以交互,只要交互原则仍被遵守。松耦合能让我们建立有弹性的OO系统,将对象之间的互相依赖降到最低。
可观察者不知道观察者的细节,只知道观察者实现了观察者接口。
tips:
信息更新可以推给观察者或者观察者从主题对象拉。(推更适用)。
代码实现:
//观察者抽象类
class Observer {
public:
virtual void update(float tmp, float hum, float pre) = 0;
virtual ~Observer(){}
};
//展示抽象类
class Display {
public:
virtual void display() const = 0;
virtual ~Display (){}
};
//主题抽象类
class Subject {
public:
virtual void registerObserver( Observer* b) = 0;
virtual void removeObserver( Observer* b) = 0;
virtual void notifyObserver() = 0;
virtual ~Subject (){}
};
class WeatherData :public Subject {
private:
std::vector<Observer*> observers;
float temperature=0;
float humidity=0;
float pressure=0;
public:
WeatherData() :Subject() { }
void registerObserver( Observer* b)
{
observers.push_back(b);
}
void removeObserver(Observer* ob)
{
auto it = find(observers.begin(), observers.end(), ob);
if (it != observers.end())
observers.erase(it);
}
//通知观察者,使得所有观察者更新信息。
void notifyObserver()
{
for (auto& it : observers)
it->update(temperature, humidity, pressure);
}
void measurementsChanged()
{
notifyObserver();
}
//设置气象站天气信息并通知观察者。
void setMeasurements(float tmp, float hum, float pre)
{
temperature = tmp;
humidity = hum;
pressure = pre;
measurementsChanged();
}
~WeatherData()
{
for (auto& each : observers)
{
delete each;
each = nullptr;
}
}
};
class CurrentConditionsDisplay :public Observer, public Display {
private:
float temperature=0;
float humidity=0;
Subject* weatherData=nullptr;
public:
//初始化信息板,并在气象站对其登记。
CurrentConditionsDisplay(Subject* wd) :Observer(), Display()
{
weatherData = wd;
weatherData->registerObserver(this);
}
//更新天气信息并展示。
void update(float tmp, float hum, float pre)
{
temperature = tmp;
humidity = hum;
display();
}
void display() const
{
printf("Current conditions: %.2f F degrees and %.2f %% humidity\n", temperature, humidity);
}
~CurrentConditionsDisplay()
{
if (weatherData)
{
delete weatherData;
weatherData = nullptr;
}
}
};
int main()
{
{
WeatherData* wd = new WeatherData();
CurrentConditionsDisplay* cd = new CurrentConditionsDisplay(wd);
//wd修改天气信息 并通知展示板
wd->setMeasurements(80, 65, 30.4f);
wd->setMeasurements(60, 35, 32.1f);
wd->removeObserver(cd);
wd->setMeasurements(60, 35, 31.1f);
}
system("pause");
}
别的适用场合:
比如按钮按下的监听事件,不同的监听者即是观察者。按钮按下会通知监听者,执行对应的操作。