观察者模式
- 观察者模式可以帮观察者知悉主题的现况。观察者对象甚至在运行的时候可决定是否要继续被主题通知。
- 观察者模式一般被运用于一个需要通知的主题对象,对应多个需要接收消息的观察者对象。可以动态的添加和删除观察者对象。
- 观察者模式,观察者和主题之间是松耦合的,体现的设计原则:
- 为了实现交互对象之间的松耦合设计而努力。
- 针对接口编程,不针对实现编程
- 多用组合,少用继承
- 观察者模式定义了对象之间一对多的关系。
- 主题用一个共同的接口来更新观察者
- 可观察者不知道观察者的细节,只知道管擦在实现了观察者接口
例子
//展示方法抽象类
class DisplayElement{
public:
virtual void display() const=0;
virtual ~DisplayElement(){}
};
//观察者抽象类
class Observer{
public:
virtual void update(const float& ,const float& ,const float&)=0;
virtual ~Observer(){}
};
class Subject{
public:
virtual bool registerObserver(Observer*)=0;
virtual bool removeObserver(Observer*)=0;
virtual void notifyObserver()=0;
virtual ~Subject(){}
};
class WeatherData:public Subject{
private:
vector<Observer*> observers;
float temp=0,humidity=0,pressure=0;
public:
WeatherData(){}
~WeatherData(){
for(Observer*& it:observers){
if(it!=nullptr){
delete it;
it=nullptr;
}
}
}
virtual bool registerObserver( Observer* newobserver){
if(newobserver==nullptr){
return false;
}
observers.push_back(newobserver);
return true;
}
virtual bool removeObserver(Observer* oldobserver){
int i=-1;
for(Observer*& it:observers){
++i;
if(it==oldobserver){
observers.erase(observers.begin()+i);
return true;
}
}
return false;
}
private:
virtual void notifyObserver(){
for(const auto& it:observers){
it->update(temp,humidity,pressure);
}
}
void measurementsChanged(){
notifyObserver();
}
public:
void getTemp(const float& m_temp){
temp=m_temp;
measurementsChanged();
}
void getHumidity(const float& m_humidity){
humidity=m_humidity;
measurementsChanged();
}
void getPressure(const float& m_pressure){
pressure=m_pressure;
measurementsChanged();
}
void setData(const float& m_temp,const float& m_hum,const float& pre){
temp=m_temp;
humidity=m_hum;
pressure=pre;
measurementsChanged();
}
};
class CurrentConditionsDisplay:public Observer,public DisplayElement{
private:
float temp,humidity,pressure;
Subject* weather=nullptr;
public:
CurrentConditionsDisplay(Subject* m_weather):weather(m_weather){
}
~CurrentConditionsDisplay(){
if(weather){
delete weather;
weather=nullptr;
}
}
virtual void update(const float& m_temp,const float& m_humidity,const float& m_pressure){
temp=m_temp;
humidity=m_humidity;
pressure=m_pressure;
display();
}
virtual void display() const{
cout<<"CurrentConditionsDisplay:"<<endl;
cout<<" temp="<<temp<<" humidity="<<humidity<<" pressure"<<pressure<<endl<<endl;
}
void giveupObserver(){
weather->removeObserver(this);
}
void startObserver(){
weather->registerObserver(this);
}
};
class ForecasDisplay:public Observer,public DisplayElement{
private:
float temp,humidity,pressure;
Subject* weather=nullptr;
public:
ForecasDisplay(Subject* m_weather):weather(m_weather){
}
~ForecasDisplay(){
if(weather){
delete weather;
weather=nullptr;
}
}
virtual void update(const float& m_temp,const float& m_humidity,const float& m_pressure){
temp=m_temp;
humidity=m_humidity;
pressure=m_pressure;
display();
}
virtual void display() const{
cout<<"ForecasDisplay:"<<endl;
cout<<" temp="<<temp<<" humidity="<<humidity<<" pressure"<<pressure<<endl<<endl;
}
void giveupObserver(){
weather->removeObserver(this);
}
void startObserver(){
weather->registerObserver(this);
}
};
int main(){
WeatherData* weather = new WeatherData; //对象
CurrentConditionsDisplay* display1 = new CurrentConditionsDisplay(weather);
ForecasDisplay* display2 = new ForecasDisplay(weather);
weather->registerObserver(display1);
//weather->registerObserver(display2); 主题主动添加观察者
display2->startObserver(); //观察者主动启动主题开始观察
//更新数据
weather->setData(12,34,56);
//display1放弃观察
display1->giveupObserver();
weather->setData(45,4,6);
return 0;
}