在HeadFrist 中的第二章中介绍了观察者模式,书中是这么定义观察者模式的;定义对象之间一对多的依赖,这样一来当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新。
这一章貌似只讲到了一个设计原则:使对象之间的耦合度竟可能的低,我的理解是,虽然对象之间存在一定的依赖关系,但是可以很容易用另外的对象来替换当前正在使用的对象。这里会用一个气象站的设计来缠身观察者模式
在讲述策略模式的时候我们分别提到了,三种设计原则:1。找出程序中的变化部分,然后将其与固定的地方分离开来;这个原则体现在display方法是变化的各个显示器的显示方式与方法一定是不一样的,所有将display设计成为接口,抽象类,独立实现,程序中体现的不明显
2.针对接口编程,而不是针对实现编程,所有的观察者都可以互相替换以及主题都是针对接口实现;
3。多用组合少用集成,我们都是只用到了一层继承,而且多处用到了组合
用c++ 实现设计模式,让我的c++ 学习了很多
C++(观察者模式)实现气象站的规划和设计,源码如下:
/****************************************
the case which is a project ,wether to
demonstrate observer patter
**************************************/
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
/***************************************
*observer
***************************************/
class Observer{//interface abstract class
public:
Observer(){}
virtual void update(float temperature,float humidity,float pressure)=0;
~Observer(){}
};
/******************************************
*subject
********************************************/
class Subject{//interface
public:
Subject(){}
virtual void registerObserver(Observer *o)=0;
virtual void removeObserver(Observer *o)=0;
virtual void notifyObserver()=0;
virtual void setMeasurements(float temperature,float humidity,float pressure)=0;
~Subject(){
vector<Observer *>::iterator iter1,iter2,temp;
for(iter1=observers.begin(),iter2=observers.end();iter1!=iter2;)
{
temp=iter1;
++iter1;
observers.erase(temp);
}
observers.clear();
}
protected:
vector<Observer *> observers;
};
//ture subject
class WeatherData:public Subject{
private:
float temperature;
float humidity;
float pressure;
public:
WeatherData(){}
void registerObserver(Observer *o){
observers.push_back(o);
}
void removeObserver(Observer *o){
vector<Observer *>::iterator iter;
iter=find(observers.begin(),observers.end(),o);
if(iter!=observers.end())
{//here can't use while ,because erase is forward translations
observers.erase(iter);
}
}
void notifyObserver(){
vector<Observer *>::iterator iter=observers.begin();
for(;iter!=observers.end();iter++)
(*iter)->update(temperature,humidity,pressure);
}
void measurementsChanged(){
notifyObserver();
}
void setMeasurements(float temperature,float humidity,float pressure){
this->temperature =temperature;
this->humidity=humidity;
this->pressure=pressure;
measurementsChanged();
}
~WeatherData(){}
};
/************************************
display information in Bulletin Board
*************************************/
class DisplayElement{
public:
DisplayElement(){}
virtual void display()=0;
~DisplayElement(){}
};
/*************************************
concrete panel
**********************************/
class CurrentCondition:public Observer{
private:
float temperature;
float humidity;
float pressure;
public:
// CurrentConditionsDisplay(){
// this->weatherData=weatherData;
// weatherData.registerObserver(this);
// }
void display(){
cout<<"current conditions: "<<temperature<<" F degrees and "<<humidity<<" %humidity and "<<pressure<<" pressure"<<endl;}
void update(float temperature,float humidity,float pressure)
{
this->temperature=temperature;
this->humidity=humidity;
this->pressure=pressure;
display();
}
// ~CurrentConditionsDisplay(){}
};
class StatisticsConditions:public Observer{
private:
float temperature;
float humidity;
float pressure;
public:
// CurrentConditionsDisplay(){
// this->weatherData=weatherData;
// weatherData.registerObserver(this);
// }
void display(){
cout<<"Statistics conditions: "<<temperature<<" F degrees and "<<humidity<<" %humidity and "<<pressure<<" pressure"<<endl;}
void update(float temperature,float humidity,float pressure)
{
this->temperature=temperature;
this->humidity=humidity;
this->pressure=pressure;
display();
}
// ~CurrentConditionsDisplay(){}
};
int main()
{
// CurrentConditionsDisplay *currentDisplay=new CurrentConditionsDisplasy();
Subject *weatherdata=new WeatherData();
// Observer *currentDisplay=new D();
Observer *currentDisplay=new CurrentCondition();
Observer *statistics=new StatisticsConditions();
weatherdata->registerObserver(currentDisplay);
weatherdata->registerObserver(statistics);
weatherdata->setMeasurements(80.0,65.0,30.4);
/**********************************
case 2
***********************************/
weatherdata->removeObserver(currentDisplay);
cout<<"after remove currentDisplay"<<endl;
weatherdata->setMeasurements(90.0,85.0,80.4);
return 0;
}