1,核心:
很多个观察者关注一个object.
因此这些个observer注册同一个object.
object的变化调用NotifyAll,引起每个observer调用自己的update.
2,先给出一个实例:
很多个观察者关注一个object.
因此这些个observer注册同一个object.
object的变化调用NotifyAll,引起每个observer调用自己的update.
2,先给出一个实例:
#include <iostream>
#include <list>
#include <cassert>
using namespace std;
class Observer;
class Subject
{
protected:
virtual ~Subject() = 0;
public:
//注册观察者
virtual void registerObserver( Observer* o ) = 0;
//移除
virtual void removeObserver( Observer* o ) = 0;
//通知
virtual void notifyObservers() const = 0;
};
Subject::~Subject() {}
class DisplayElement
{
public:
virtual void display() const = 0;
protected: virtual ~DisplayElement() = 0;
};
DisplayElement::~DisplayElement() {}
class Observer //观察者基类
{
protected:
virtual ~Observer() = 0 ;
public:
//观察者得到通知,进行改变.
virtual void update(float temp, float humidity, float pressure) = 0;
};
Observer::~Observer() {}
/*********************object*************************/
class WeatherData : public Subject
{
public:
WeatherData() : _temperature( 0.0 ), _humidity( 0.0 ), _pressure( 0.0 )
{}
void registerObserver( Observer* o )
{
assert( o );
_observers.push_back(o);
}
void removeObserver( Observer* o )
{
assert( o );
_observers.remove(o);
}
void notifyObservers() const
{
for( list< Observer* >::iterator iterator = _observers.begin(); _observers.end() != iterator; ++iterator )
{
(*iterator) -> update( _temperature, _humidity, _pressure );
}
}
void measurementsChanged()
{
notifyObservers();
}
void setMeasurements( float temperature, float humidity, float pressure )
{
_temperature = temperature;
_humidity = humidity;
_pressure = pressure;
measurementsChanged();
}
// other WeatherData methods here
float getTemperature() const
{
return _temperature;
}
float getHumidity() const
{
return _humidity;
}
float getPressure() const
{
return _pressure;
}
private:
WeatherData( const WeatherData& ); // Disable copy constructor
void operator=( const WeatherData& ); // Disable assignment operator
private:
mutable list< Observer* > _observers;
float _temperature;
float _humidity;
float _pressure;
};
/*********************observer*************************/
class CurrentConditionsDisplay : private Observer, private DisplayElement //观察者1
{
public:
explicit CurrentConditionsDisplay( Subject* weatherData ) :
_weatherData( weatherData ), _temperature( 0.0 ), _humidity( 0.0 )
{
assert( weatherData );
_weatherData -> registerObserver( this ); //构造,注册
}
~CurrentConditionsDisplay()
{
_weatherData->removeObserver( this ); //析构 移除
}
void update( float temperature, float humidity, float pressure )
{
_temperature = temperature;
_humidity = humidity;
display();
}
void display() const
{
cout.setf( ios::showpoint );
cout.precision(3);
cout << "Current conditions: " << _temperature;
cout << " F degrees and " << _humidity;
cout << "% humidity" << endl;
}
private:
CurrentConditionsDisplay( const CurrentConditionsDisplay& ); // Disable copy constructor
void operator=( const CurrentConditionsDisplay& ); // Disable assignment operator
private:
Subject* _weatherData;
float _temperature;
float _humidity;
};
class ForecastDisplay : private Observer, private DisplayElement
{
public:
explicit ForecastDisplay( WeatherData* weatherData ) :
_weatherData( weatherData ), _currentPressure( 29.92F ), _lastPressure( 0 )
{
assert( weatherData );
weatherData->registerObserver( this );
}
~ForecastDisplay()
{
_weatherData->removeObserver( this );
}
void update( float temp, float humidity, float pressure )
{
_lastPressure = _currentPressure;
_currentPressure = pressure;
display();
}
void display() const
{
cout.setf( ios::showpoint );
cout.precision(3);
cout << "Forecast: ";
if( _currentPressure > _lastPressure )
{
cout << "Improving weather on the way!";
}
else if( _currentPressure == _lastPressure )
{
cout << "More of the same";
}
else if( _currentPressure < _lastPressure )
{
cout << "Watch out for cooler, rainy weather";
}
cout << endl;
}
private:
ForecastDisplay( const ForecastDisplay& ); // Disable copy constructor
void operator=( const ForecastDisplay& ); // Disable assignment operator
private:
WeatherData* _weatherData;
float _currentPressure;
float _lastPressure;
};
class StatisticsDisplay : private Observer, private DisplayElement
{
public:
explicit StatisticsDisplay( WeatherData* weatherData ) :
_weatherData( weatherData ), _maxTemp( 0.0 ), _minTemp( 200.0F ), _tempSum( 0.0 ), _numReadings( 0 )
{
assert( weatherData );
_weatherData->registerObserver( this );
}
~StatisticsDisplay()
{
_weatherData->removeObserver( this );
}
void update( float temp, float humidity, float pressure )
{
_tempSum += temp;
_numReadings++;
if( temp > _maxTemp )
{
_maxTemp = temp;
}
if( temp < _minTemp )
{
_minTemp = temp;
}
display();
}
public: void display() const
{
cout.setf( ios::showpoint );
cout.precision(3);
cout << "Avg/Max/Min temperature = " << ( _tempSum / _numReadings );
cout << "/" << _maxTemp << "/" << _minTemp << endl;
}
private:
StatisticsDisplay( const StatisticsDisplay& ); // Disable copy constructor
void operator=( const StatisticsDisplay& ); // Disable assignment operator
private:
WeatherData* _weatherData;
float _maxTemp;
float _minTemp;
float _tempSum;
int _numReadings;
};
class HeatIndexDisplay : private Observer, private DisplayElement
{
public:
explicit HeatIndexDisplay( Subject* weatherData ) :
_weatherData( weatherData ), _heatIndex( 0.0 )
{
assert( weatherData );
_weatherData->registerObserver( this );
}
~HeatIndexDisplay()
{
_weatherData->removeObserver( this );
}
void update( float t, float rh, float pressure )
{
_heatIndex = computeHeatIndex( t, rh );
display();
}
float computeHeatIndex( float t, float rh ) const
{
float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh)
+ (0.00941695 * (t * t) ) + (0.00728898 * (rh * rh) )
+ (0.000345372 * (t * t * rh) ) - (0.000814971 * (t * rh * rh) ) +
(0.0000102102 * (t * t * rh * rh) ) - (0.000038646 * (t * t * t) ) + (0.0000291583 *
(rh * rh * rh) ) + (0.00000142721 * (t * t * t * rh) ) +
(0.000000197483 * (t * rh * rh * rh) ) - (0.0000000218429 * (t * t * t * rh * rh) ) +
0.000000000843296 * (t * t * rh * rh * rh) ) -
(0.0000000000481975 * (t * t * t * rh * rh * rh) ) );
return index;
}
void display() const
{
cout.setf( ios::showpoint);
cout.precision(7);
cout << "Heat index is " << _heatIndex << endl;
}
private:
HeatIndexDisplay( const HeatIndexDisplay& ); // Disable copy constructor
void operator=( const HeatIndexDisplay& ); // Disable assignment operator
private:
Subject* _weatherData;
float _heatIndex;
};
int main()
{
WeatherData weatherData;
CurrentConditionsDisplay currentDisplay( &weatherData );
StatisticsDisplay statisticsDisplay( &weatherData );
ForecastDisplay forecastDisplay( &weatherData );
HeatIndexDisplay heatIndexDisplay( &weatherData );
weatherData.setMeasurements( 80, 65, 30.4f );
weatherData.setMeasurements( 82, 70, 29.2f );
weatherData.setMeasurements( 78, 90, 29.2f );
return 0;
}