觀察者模式

氣象觀測(cè)站

你的團(tuán)隊(duì)接到一個(gè)任務(wù)入热,建立一個(gè)能顯示氣象站數(shù)據(jù)的應(yīng)用拍棕,可以添加或移除布告板,布告板默認(rèn)有 目前狀況才顿,氣象統(tǒng)計(jì)莫湘,天氣預(yù)測(cè)。用戶可以隨時(shí)添加或移除布告板郑气。提供一個(gè)WeatherData對(duì)象幅垮,可以從氣象站獲得溫度,濕度尾组,氣壓等信息忙芒。
大概長(zhǎng)這樣


1-5

錯(cuò)誤的實(shí)現(xiàn)

WeatherData類長(zhǎng)這樣


1-6

直接再函數(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);
}

有哪些不妥

  1. 我們是針對(duì)實(shí)現(xiàn)編程,而不是針對(duì)接口讳侨。
  2. 對(duì)于每一個(gè)布告板呵萨,我們都要修改代碼
  3. 我們無法動(dòng)態(tài)的增加或刪除布告板
    。跨跨。潮峦。

使用觀察者模式

出版者 + 訂閱者 = 觀察者模式


1-7

設(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();
}

程序輸出


1-8

首先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)更新础米。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市添诉,隨后出現(xiàn)的幾起案子屁桑,更是在濱河造成了極大的恐慌,老刑警劉巖栏赴,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掏颊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡艾帐,警方通過查閱死者的電腦和手機(jī)乌叶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來柒爸,“玉大人准浴,你說我怎么就攤上這事∩又桑” “怎么了乐横?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)今野。 經(jīng)常有香客問我葡公,道長(zhǎng),這世上最難降的妖魔是什么条霜? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任催什,我火速辦了婚禮,結(jié)果婚禮上宰睡,老公的妹妹穿的比我還像新娘蒲凶。我一直安慰自己,他們只是感情好拆内,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布旋圆。 她就那樣靜靜地躺著,像睡著了一般麸恍。 火紅的嫁衣襯著肌膚如雪灵巧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天抹沪,我揣著相機(jī)與錄音刻肄,去河邊找鬼。 笑死采够,一個(gè)胖子當(dāng)著我的面吹牛肄方,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹬癌,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼权她,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了逝薪?” 一聲冷哼從身側(cè)響起隅要,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎董济,沒想到半個(gè)月后步清,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年廓啊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欢搜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谴轮,死狀恐怖炒瘟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情第步,我是刑警寧澤疮装,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站粘都,受9級(jí)特大地震影響廓推,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翩隧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一樊展、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸽心,春花似錦滚局、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至糯景,卻和暖如春嘁圈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蟀淮。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工最住, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怠惶。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓涨缚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親策治。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脓魏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容