觀察者模式

我們先看看報社和雜誌的訂閱是怎麼回事:

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章