观察者模式

来源:互联网 发布:分层数据流程图 编辑:程序博客网 时间:2024/06/09 12:53

观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新。

关键:用组合和委托来代替继承


注:注意有一个实现Observer接口的对象列表,可以随时增加观察者。

特别注意具体的观察者必须注册具体主题。

当有新的具体类需要当观察者,所有要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。

设计气象站如下:


注意:

1.在WeatherData中,会用一个链表来存储当前的观测者。

2.在notifyObeservers()中,会将链表中每一个观察者的update调用。

3.measurementsChanged()中会调用notifyObeservers()。

4.布告板实现

class CurrentConditionsDisplay :public Observer, public DisplayElement{private:float temperature;float humidity;Subject weatherData;public:CurrentConditionsDisplay(Subject weatherData)  //构造器需要weatherData对象作为注册用{this.weatherData = weatherData;weatherData.registerObserver(this);}void update(float temperature, float humidity, float pressure){this.temperature = temperature;this.humidity = humidity;display();}void display(){//}};
5.上面布告板的构造需要具体主题对象。保存该对象的引用的目的是防止以后取消注册时使用。

#include <iostream>#include <vector>#include <string>#include <list>using namespace std;/*观察者抽象类*/class Observer{public:virtual void update(float temp, float humidity, float pressure) = 0;  //当主题数据发生变化时,会调用观察者的这个函数};/*主题抽象类*/class Subject{public:virtual void registerObserver(Observer *ob) = 0;virtual void removeObserver(Observer *ob) = 0;virtual void notifyObservers() = 0;  //当主题状态改变时,这个方法会被调用,以通知所有的观察者};/*天气数据类*/class WeatherData :public Subject{private:list<Observer *> observers;   //加上一个链表来记录观察者float temperature;float humidity;float pressure;public:void registerObserver(Observer *ob){observers.push_back(ob);  //添加到链表里}void removeObserver(Observer *ob){observers.remove(ob);     //从链表里删除吧}void notifyObservers(){for (list<Observer *>::iterator it = observers.begin(); it != observers.end(); ++it){Observer *observer = *it;observer->update(temperature, humidity, pressure);  //调用观察者的更新函数}}void measurementsChanged(){notifyObservers();}void setMeasurements(float _temp, float _hum, float _pre){temperature = _temp;humidity = _hum;pressure = _pre;measurementsChanged();}/*其他方法*/};/*显示板抽象类*/class DisplayElement{public:virtual void display() = 0;};/*布告板类*/class CurrentConditionDisplay :public Observer,public DisplayElement{ //所有布告板也是一个观察者了private:float temperature;float humidity;Subject *weatherData;public:CurrentConditionDisplay(Subject *_wD) :weatherData(_wD){weatherData->registerObserver(this);  //把布告板加入到_wD的观察者集中}void update(float _temp, float _hum, float _pre){temperature = _temp;humidity = _hum;display();}void display(){cout << "Current conditions: " << temperature << "F degrees and " << humidity << "% humidity" << endl;}};/*还可以创建其他功能的布告板*/int main(void){ WeatherData *weatherData = new WeatherData();CurrentConditionDisplay *currentDisplay1 = new  CurrentConditionDisplay(weatherData);/*此处还可以创建其他功能的布告板实例*/weatherData->setMeasurements(80, 65, 30.4f);weatherData->setMeasurements(82, 70, 29.2f);weatherData->setMeasurements(78, 90, 29.2f);delete weatherData;delete currentDisplay1;return 0;}

一定要理解,其实每一个布告板就是一个观察者。


让我想起了阿里的一道笔试题,其实就是观察者模式啊!!!

题目如下:

在某个工厂的的生成一件产品(A,B,C,...)。其中产品A依赖半成品和原来(E,F,G,...)。其中半成品B又依赖于其他半成品或原料(H,I,...)。现在发现原料X发生质量问题,所以由原料X制成的半成品或产品以及直接或间接依赖这些半成品的生成物都要销毁掉。请设计一个C++数据结构来描述这些原料,半成品和最终产品的依赖关系,能够满足以下两个常用请求的速度要求。

一:指定的产品A,列出它所需要的原料列表A-Set。

二:并且给出指定的原料X发生质量问题的所有需要销毁的半成品或产品的列表。


0 0
原创粉丝点击