氣象觀測(cè)站
你的團(tuán)隊(duì)接到一個(gè)任務(wù)入热,建立一個(gè)能顯示氣象站數(shù)據(jù)的應(yīng)用拍棕,可以添加或移除布告板,布告板默認(rèn)有 目前狀況才顿,氣象統(tǒng)計(jì)莫湘,天氣預(yù)測(cè)。用戶可以隨時(shí)添加或移除布告板郑气。提供一個(gè)WeatherData對(duì)象幅垮,可以從氣象站獲得溫度,濕度尾组,氣壓等信息忙芒。
大概長(zhǎng)這樣
錯(cuò)誤的實(shí)現(xiàn)
WeatherData類長(zhǎng)這樣
直接再函數(shù)中通知每一個(gè)布告板
void WeatherData::measurementsChanged(){
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
//通知每一個(gè)布告板
bgb1.updata(temp,humidity,pressure);
bgb2.updata(temp,humidity,pressure);
bgb3.updata(temp,humidity,pressure);
}
有哪些不妥
- 我們是針對(duì)實(shí)現(xiàn)編程,而不是針對(duì)接口讳侨。
- 對(duì)于每一個(gè)布告板呵萨,我們都要修改代碼
- 我們無法動(dòng)態(tài)的增加或刪除布告板
。跨跨。潮峦。
使用觀察者模式
出版者 + 訂閱者 = 觀察者模式
設(shè)計(jì)好出題和觀察者的抽象基類,讓W(xué)eatherData繼承主題勇婴,布告板繼承觀察者忱嘹。實(shí)現(xiàn)方式有很多,一種是Subject維護(hù)一個(gè)Observer對(duì)象的數(shù)組
class Observer{
virtual void update(float temp,float humidity,float pressure)=0;
};
class Subject{
public:
virtual void registerObserver(Observer * po)=0;
virtual void removeObserver(Observer * po)=0;
virtual void notifyObservers()=0;
protected:
vector<Observer *> oblist;
};
具體實(shí)現(xiàn)
WeatherData
class WeatherData:public Subject{
public:
virtual void registerObserver(Observer * po);
virtual void removeObserver(Observer * po);
virtual void notifyObservers();
void setdata(float t,float h,float p);
private:
float temperature;
float humidity;
float pressure;
};
void WeatherData::registerObserver(Observer * po){
oblist.push_back(po);
}
void WeatherData::removeObserver(Observer * po){
int i;
for(i=0;i<oblist.size();i++){
if(oblist[i]==po){
oblist.erase(oblist.begin()+i);
break;
}
}
}
void WeatherData::notifyObservers(){
for(int i=0;i<oblist.size();i++){
oblist[i]->update(temperature,humidity,pressure);
}
}
void WeatherData::setdata(float t,float h,float p){
temperature=t;
humidity=h;
pressure=p;
notifyObservers();
}
布告板
class Bgb:public Observer{//布告板
public:
virtual void update(float temp,float humidity,float pressure);
void display();//打印
private:
float t,h,p;//存放接受數(shù)據(jù)
};
void Bgb::update(float temp,float humidity,float pressure){
t=temp; h=humidity; p=pressure;
}
void Bgb::display(){
cout<<"Bjb * is"<<(int *)(this) <<endl;
cout<<"temperature is :"<<t<<" humidity is :"<<h<<" pressure is :"<<p<<endl;
}
完整測(cè)試代碼
#include <iostream>
#include <vector>
using namespace std;
class Observer{
public:
virtual void update(float temp,float humidity,float pressure)=0;
};
class Subject{
public:
virtual void registerObserver(Observer * po)=0;
virtual void removeObserver(Observer * po)=0;
virtual void notifyObservers()=0;
protected:
vector<Observer *> oblist;
};
//----------------------------------------------------------
class WeatherData:public Subject{
public:
virtual void registerObserver(Observer * po);
virtual void removeObserver(Observer * po);
virtual void notifyObservers();
void setdata(float t,float h,float p);
private:
float temperature;
float humidity;
float pressure;
};
class Bgb:public Observer{//布告板
public:
virtual void update(float temp,float humidity,float pressure);
void display();//打印
private:
float t,h,p;//存放接受數(shù)據(jù)
};
//----------------------------------------------------------
int main(){
WeatherData WD; //一個(gè)主題
Bgb bjb1,bjb2,bjb3; //三個(gè)觀察者
WD.registerObserver(&bjb1);//注冊(cè)
WD.registerObserver(&bjb2);
WD.registerObserver(&bjb3);
WD.setdata(1,2,3);
bjb1.display();//打印每個(gè)觀察者得到的信息
bjb2.display();
bjb3.display();
cout<<endl;
WD.removeObserver(&bjb3);//bjb3 取消訂閱
WD.setdata(8,9,10);
bjb1.display();//再次打印
bjb2.display();
bjb3.display();
//bjb3 的信息沒有更新
return 0;
}
void Bgb::update(float temp,float humidity,float pressure){
t=temp; h=humidity; p=pressure;
}
void Bgb::display(){
cout<<"Bjb * is"<<(int *)(this) <<endl;
cout<<"temperature is :"<<t<<" humidity is :"<<h<<" pressure is :"<<p<<endl;
}
void WeatherData::registerObserver(Observer * po){
oblist.push_back(po);
}
void WeatherData::removeObserver(Observer * po){
int i;
for(i=0;i<oblist.size();i++){
if(oblist[i]==po){
oblist.erase(oblist.begin()+i);
break;
}
}
}
void WeatherData::notifyObservers(){
for(int i=0;i<oblist.size();i++){
oblist[i]->update(temperature,humidity,pressure);
}
}
void WeatherData::setdata(float t,float h,float p){
temperature=t;
humidity=h;
pressure=p;
notifyObservers();
}
程序輸出
首先3個(gè)布告板都訂閱耕渴,更新數(shù)據(jù) 1 2 3
然后布告板3取消訂閱
更新數(shù)據(jù) 8 9 10
只有bgb3沒有收到
觀察者模式
定義了對(duì)象之間一對(duì)多的依賴拘悦,這樣一來,當(dāng)一個(gè)對(duì)象改變狀態(tài)時(shí)橱脸,他的所有依賴者都會(huì)收到通知并自動(dòng)更新础米。