C++設(shè)計(jì)模式編程中的觀察者模式使用示例
概述:
最近中國(guó)股市起起伏伏,當(dāng)然了起伏就用商機(jī),小明發(fā)現(xiàn)商機(jī)后果斷想入市,買入了中國(guó)證券,他想在電腦客戶端上,網(wǎng)頁(yè)上,手機(jī)上,iPad上都可以查看到該證券的實(shí)時(shí)行情,這種情況下我們應(yīng)該怎么設(shè)計(jì)我們的軟件呢?我們可以這樣:小明的所有客戶端上都訂閱中國(guó)證券這個(gè)股票,只要股票一有變化,所有的客戶端都會(huì)被通知到并且被自動(dòng)更新。
這就是我們的觀察者模式,她定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí), 所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。
類圖:
可以看出,在這個(gè)觀察者模式的實(shí)現(xiàn)里有下面這些角色:
抽象主題(Subject)角色:主題角色把所有對(duì)觀察考對(duì)象的引用保存在一個(gè)聚集里,每個(gè)主題都可以有任何數(shù)量的觀察者。抽象主題提供一個(gè)接口,可以增加和刪除觀察者對(duì)象,主題角色又叫做抽象被觀察者(Observable)角色,一般用一個(gè)抽象類或者一個(gè)接口實(shí)現(xiàn)。
抽象觀察者(Observer)角色:為所有的具體觀察者定義一個(gè)接口,在得到主題的通知時(shí)更新自己。這個(gè)接口叫做更新接口。抽象觀察者角色一般用一個(gè)抽象類或者一個(gè)接口實(shí)現(xiàn)。在這個(gè)示意性的實(shí)現(xiàn)中,更新接口只包含一個(gè)方法(即Update()方法),這個(gè)方法叫做更新方法。
具體主題(ConcreteSubject)角色:將有關(guān)狀態(tài)存入具體現(xiàn)察者對(duì)象;在具體主題的內(nèi)部狀態(tài)改變時(shí),給所有登記過(guò)的觀察者發(fā)出通知。具體主題角色又叫做具體被觀察者角色(Concrete Observable)。具體主題角色通常用一個(gè)具體子類實(shí)現(xiàn)。
具體觀察者(ConcreteObserver)角色:存儲(chǔ)與主題的狀態(tài)自恰的狀態(tài)。具體現(xiàn)察者角色實(shí)現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題的狀態(tài)相協(xié)調(diào)。如果需要,具體現(xiàn)察者角色可以保存一個(gè)指向具體主題對(duì)象的引用。具體觀察者角色通常用一個(gè)具體子類實(shí)現(xiàn)。
從具體主題角色指向抽象觀察者角色的合成關(guān)系,代表具體主題對(duì)象可以有任意多個(gè)對(duì)抽象觀察者對(duì)象的引用。之所以使用抽象觀察者而不是具體觀察者,意味著主題對(duì)象不需要知道引用了哪些ConcreteObserver類型,而只知道抽象Observer類型。這就使得具體主題對(duì)象可以動(dòng)態(tài)地維護(hù)一系列的對(duì)觀察者對(duì)象的引用,并在需要的時(shí)候調(diào)用每一個(gè)觀察者共有的Update()方法。這種做法叫做"針對(duì)抽象編程"。
概念
觀察者模式是講有一個(gè)目標(biāo),眾多個(gè)觀察者去“觀察”目標(biāo)。目標(biāo)是目標(biāo)抽象類的一個(gè)派生類,觀察者是觀察者抽象類的一個(gè)派生類。當(dāng)目標(biāo)類的數(shù)據(jù)改變,所有對(duì)應(yīng)的觀察者對(duì)應(yīng)去更新自己的狀態(tài)
可以使用的情況:比如有一個(gè)世界時(shí)鐘程序,有多個(gè)圖形時(shí)鐘去顯示比如北京時(shí)區(qū),巴黎時(shí)區(qū),等等。如果設(shè)置一個(gè)北京時(shí)間,那么其他時(shí)鐘圖形都需要更新(加上或者減去時(shí)差值)。典型的圖形界面設(shè)計(jì)隨處可見,一個(gè)溫度程序,在溫度濕度等條件改變時(shí),要更新多種顯示圖形來(lái)呈現(xiàn)。
實(shí)例
使用時(shí),首先定義一個(gè)Subject的類對(duì)象,然后再定義多個(gè)Observer類(派生類)對(duì)象,每個(gè)Observer對(duì)象指定自己被注冊(cè)到哪個(gè)Subject對(duì)象內(nèi)。
示例:
#include<vector> #include<iostream> #include<string> using namespace std; class Subject; class Observer{ //觀察者抽象類 public: virtual void update(Subject *base)=0; protected: Subject * _subject; }; class Subject{ //目標(biāo)抽象類 public: string s1; //數(shù)據(jù)值,可以作為私有數(shù)據(jù),然后定義一個(gè)借口去返回值,這里為了省事 int i1; //數(shù)據(jù)值 void regiObserver(Observer *obs){ _observer.push_back(obs); cout<<"已注冊(cè)"<<endl; } void deleObserver(Observer *obs){ _observer.pop_back(); } void notify(){ //更新所有的觀察者 vector<Observer *>::iterator it; for(it = _observer.begin(); it != _observer.end(); it++) (*it)->update(this); } private: vector<Observer *> _observer; //觀察者容器 }; class FSubject:public Subject{ public: void set(string s,int i){ s1 = s; i1 = i; notify(); //通知觀察者。主函數(shù)的執(zhí)行順序已經(jīng)保證了所有的觀察者都已經(jīng)進(jìn)入容器內(nèi) } }; class FObserver :public Observer{ //第一個(gè)觀察者派生類 public: FObserver(Subject *base):Observer(){ _subject = base; _subject->regiObserver(this); } void update(Subject *base){ s1 = base->s1; i1 = base->i1; display(); } void display(){ cout<<"更新值,第一個(gè)\n"<<s1<<endl; cout<<i1<<endl; } private: string s1; int i1; }; class SObserver:public Observer{ //第二個(gè)觀察者派生類 public: SObserver(Subject * base){ _subject = base; _subject->regiObserver(this); } void update(Subject *base){ s1 = base->s1; i1 = base->i1; display(); } void display(){ cout<<"更新值,第二個(gè)\n"<<s1<<endl; cout<<i1<<endl; } private: string s1; int i1; }; int main() { FSubject * sub = new FSubject; FObserver * one = new FObserver(sub); SObserver * two = new SObserver(sub); sub->set("ok",3); return 0;
}
Subject 類中的容器對(duì)象維護(hù)者所有對(duì)觀察者的引用,目的是在notify中去更新所有的觀察者,即通過(guò)遍歷去調(diào)用觀察者->update()。
觀察者中的update()作用是完成觀察者需要完成的事,比如在上例中,去更新自身保存的副本值,然后并顯示出來(lái)。
Observer類中有一個(gè)Subject指針?lè)浅V匾?,在觀察者的派生類的構(gòu)造函數(shù),需要去把自身的this傳遞過(guò)去進(jìn)行注冊(cè)。
Observer中有和Subject同樣的數(shù)據(jù),也可以設(shè)置為局部變量,僅僅是完成觀察者需要做的事就行,而不必存儲(chǔ)。
上一篇:深入解析設(shè)計(jì)模式中的適配器模式在C++中的運(yùn)用
欄 目:C語(yǔ)言
下一篇:使用設(shè)計(jì)模式中的單例模式來(lái)實(shí)現(xiàn)C++的boost庫(kù)
本文標(biāo)題:C++設(shè)計(jì)模式編程中的觀察者模式使用示例
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2475.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改