我們先看看報社和雜誌的訂閱是怎麼回事:
1.報社的業務是出版報紙
2.向某家報社訂閱報紙,只要他們有新報紙,就會給那你送來。只要你是他們的訂戶,你就會一直收到新報紙。
3.當你不想再看報紙的時候,取消訂閱,他們就不會再送新報紙來了。
4.只要報社還在運營,就會一直有人(或單位)向他們訂閱報紙或取消訂閱報紙。
出版者(主題)+訂閱者(觀察者)=觀察者模式
觀察者模式定義了對象之間的一對多依賴,這樣一來,當一個對象改變了狀態時,它的所有依賴者都會收到通知並自動更新。
當兩個對象之間鬆耦合,它們仍然可以交互,但是不太清楚彼此的細節。
改變主題或觀察者其中一方,並不影響另一方。因爲兩者是鬆耦合的,所以只要他們之間的接口仍被遵守,我們就可以自由的改變它們。
設計原則:爲交互對象之間的鬆耦合設計而努力。
#include <iostream>
#include <list>
#include <string>
using namespace std;
/*前向聲明*/
class Observer;
/*主題接口*/
class Subject
{
public:
virtual void attach(Observer *o)=0;
virtual void change()=0;
virtual void setWeather(string str)=0;
virtual string getWeather()=0;
};
/*觀察者接口*/
class Observer
{
public:
virtual string getName()=0;
virtual void update(Subject *s)=0;
};
/*主題實現*/
class Earth: public Subject
{
private:
string weather;
list<Observer* > *l;//指針
public:
Earth(){
l = new list<Observer*>;
}
void attach(Observer *o){
this->l->push_back(o);
}
void change(){
for(list<Observer*>::iterator it=l->begin();it!=l->end();++it)
{
(*it)->update(this);
}
}
void setWeather(string str)
{
this->weather=str;
change();
}
string getWeather()
{
return this->weather;
}
};
/*觀察者實現*/
class Satellite:public Observer
{
private:
string name;
public:
Satellite(string str)
{
name=str;
}
string getName()
{
return name;
}
void update(Subject *s)
{
cout<<this->getName()+" "+s->getWeather();
}
};
int main()
{
Earth e;
Satellite *s1 = new Satellite("風雲一號");
Satellite *s2 = new Satellite("風雲二號");
Satellite *s3 = new Satellite("風雲三號");
Satellite *s4 = new Satellite("風雲四號");
e.attach(s1);
e.attach(s2);
e.attach(s3);
e.attach(s4);
e.setWeather("fine");
delete s1;
delete s2;
delete s3;
delete s4;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
/*觀察者接口*/
class Observer{
public:
virtual void update(float temp,float humidity,float pressure)=0;
virtual ~Observer(){
//cout<<"Observer"<<endl;
}
};
/*展示接口*/
class DisplayElement{
public:
virtual void display()=0;
virtual ~DisplayElement(){
//cout<<"displayElement"<<endl;
}
};
/*主題接口*/
class Subject
{
public:
virtual void registerObserver(Observer *o)=0;/*註冊*/
virtual void notifyObserver()=0;/*通知*/
virtual ~Subject(){
//cout<<"Subject"<<endl;
}
};
/*主題實現*/
class WeatherData:public Subject{
public:
WeatherData():vec(new vector<Observer *>),temperature(0),humidity(0),pressure(0){}
void registerObserver(Observer *o)
{
vec->push_back(o);
}
void notifyObserver()
{
vector<Observer *>::iterator it=vec->begin();
while(it!=vec->end())
{
(*it)->update(temperature,humidity,pressure);
it++;
}
}
void measurementsChanged()
{
notifyObserver();
}
void setMeasurements(float t,float h,float p)
{
temperature=t;
humidity=h;
pressure=p;
measurementsChanged();
}
virtual ~WeatherData()
{
//cout<<"WeatherData"<<endl;
}
private:
vector<Observer *> *vec;
float temperature;
float humidity;
float pressure;
};
/*觀察者實現之目前狀況佈告板*/
class CurrentConditionsDisplay:public Observer,public DisplayElement
{
public:
CurrentConditionsDisplay(Subject *w):weatherData(w),temperature(0.0),humidity(0.0)
{
weatherData->registerObserver(this);
}
void update(float t,float h,float p)
{
temperature=t;
humidity=h;
display();
}
void display()
{
cout<<"Current conditions:"<<temperature<<"F degress and "<<humidity<<"%d humidity"<<endl;
}
virtual ~CurrentConditionsDisplay()
{
//cout<<"CurrentConditionsDisplay"<<endl;
}
private:
float temperature;
float humidity;
Subject *weatherData;
};
int main()
{
WeatherData *w=new WeatherData();
CurrentConditionsDisplay *c=new CurrentConditionsDisplay(w);
w->setMeasurements(80,65,30.4f);
w->setMeasurements(82,70,29.2f);
w->setMeasurements(78,90,29.2f);
delete c;
delete w;
return 0;
}