C++設(shè)計模式之觀察者模式
前言
之前做了一個性能測試的項(xiàng)目,就是需要對現(xiàn)在的產(chǎn)品進(jìn)行性能測試,獲得測試數(shù)據(jù),然后書寫測試報告,并提出合理化的改善意見。項(xiàng)目很簡單,我們獲得了一系列性能測試數(shù)據(jù),對于數(shù)據(jù),我們需要在Excel中制作測試數(shù)據(jù)的折線圖、餅狀圖和柱狀圖,以直觀的表現(xiàn)出性能的變化。在實(shí)際操作時,我發(fā)現(xiàn),如果我修改了一個數(shù)據(jù),折線圖、餅狀圖和柱狀圖就都發(fā)生了變換。這個是如何做到的?這就要說到今天總結(jié)的觀察者模式了,作為設(shè)計模式大家庭中最重要的一個,我們不得不去好好的學(xué)習(xí)一下觀察者模式。
觀察者模式
在GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對觀察者模式是這樣說的:定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。當(dāng)一個對象發(fā)生了變化,關(guān)注它的對象就會得到通知;這種交互也稱為發(fā)布-訂閱(publish-subscribe)。目標(biāo)是通知的發(fā)布者,它發(fā)出通知時并不需要知道誰是它的觀察者。
再說說上面的數(shù)據(jù)和圖之間的關(guān)系;不管是折線圖、餅狀圖,還是柱狀圖,它們都依賴于數(shù)據(jù);當(dāng)數(shù)據(jù)發(fā)生變化時,數(shù)據(jù)對象會通知依賴于它的對象去更新;所以就有了Excel中,當(dāng)數(shù)據(jù)發(fā)生變化時,對應(yīng)的統(tǒng)計圖也會自動的重繪。
UML類圖
Subject(目標(biāo))
——目標(biāo)知道它的觀察者??梢杂腥我舛鄠€觀察者觀察同一個目標(biāo);
——提供注冊和刪除觀察者對象的接口。
Observer(觀察者)
——為那些在目標(biāo)發(fā)生改變時需獲得通知的對象定義一個更新接口。
ConcreteSubject(具體目標(biāo))
——將有關(guān)狀態(tài)存入各ConcreteObserver對象;
——當(dāng)它的狀態(tài)發(fā)生改變時,向它的各個觀察者發(fā)出通知。
ConcreteObserver(具體觀察者)
——維護(hù)一個指向ConcreteSubject對象的引用;
——存儲有關(guān)狀態(tài),這些狀態(tài)應(yīng)與目標(biāo)的狀態(tài)保持一致;
——實(shí)現(xiàn)Observer的更新接口以使自身狀態(tài)與目標(biāo)的狀態(tài)保持一致。
觀察者模式按照以下方式進(jìn)行協(xié)作:
1.當(dāng)ConcreteSubject發(fā)生任何可能導(dǎo)致其觀察者與其本身狀態(tài)不一致的改變時,它將通知它的各個觀察者;
2.在得到一個具體目標(biāo)的改變通知后,ConcreteObserver對象可向目標(biāo)對象查詢信息。ConcreteObserver使用這些信息以使它的狀態(tài)與目標(biāo)對象的狀態(tài)一致。
以下是調(diào)用時序圖:
使用場合
在以下任一情況下都可以使用觀察者模式:
1.當(dāng)一個抽象模型有兩個方面,其中一個方面依賴于另一方面。將這二者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立的改變和復(fù)用;
2.當(dāng)對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變;
3.當(dāng)一個對象必須通知其它對象,而它又不能假定其它對象是誰;也就是說,你不希望這些對象是緊密耦合的。
代碼實(shí)現(xiàn)
#include <iostream>
#include <list>
using namespace std;
class Observer
{
public:
virtual void Update(int) = 0;
};
class Subject
{
public:
virtual void Attach(Observer *) = 0;
virtual void Detach(Observer *) = 0;
virtual void Notify() = 0;
};
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(Subject *pSubject) : m_pSubject(pSubject){}
void Update(int value)
{
cout<<"ConcreteObserver get the update. New State:"<<value<<endl;
}
private:
Subject *m_pSubject;
};
class ConcreteObserver2 : public Observer
{
public:
ConcreteObserver2(Subject *pSubject) : m_pSubject(pSubject){}
void Update(int value)
{
cout<<"ConcreteObserver2 get the update. New State:"<<value<<endl;
}
private:
Subject *m_pSubject;
};
class ConcreteSubject : public Subject
{
public:
void Attach(Observer *pObserver);
void Detach(Observer *pObserver);
void Notify();
void SetState(int state)
{
m_iState = state;
}
private:
std::list<Observer *> m_ObserverList;
int m_iState;
};
void ConcreteSubject::Attach(Observer *pObserver)
{
m_ObserverList.push_back(pObserver);
}
void ConcreteSubject::Detach(Observer *pObserver)
{
m_ObserverList.remove(pObserver);
}
void ConcreteSubject::Notify()
{
std::list<Observer *>::iterator it = m_ObserverList.begin();
while (it != m_ObserverList.end())
{
(*it)->Update(m_iState);
++it;
}
}
int main()
{
// Create Subject
ConcreteSubject *pSubject = new ConcreteSubject();
// Create Observer
Observer *pObserver = new ConcreteObserver(pSubject);
Observer *pObserver2 = new ConcreteObserver2(pSubject);
// Change the state
pSubject->SetState(2);
// Register the observer
pSubject->Attach(pObserver);
pSubject->Attach(pObserver2);
pSubject->Notify();
// Unregister the observer
pSubject->Detach(pObserver);
pSubject->SetState(3);
pSubject->Notify();
delete pObserver;
delete pObserver2;
delete pSubject;
}
總結(jié)
觀察者模式在23個設(shè)計模式中的地位是非常高的,我們基本上各大框架中都是隨處可見。真正的理解了整個模式,對我們?nèi)ダ斫鈩e人的代碼有非常大的幫助;在我們?nèi)蘸蟮墓ぷ髦幸矔蚨嗷蛏俚氖褂迷撛O(shè)計模式。這里總結(jié)的不是很全面,在日后如果碰到了需要補(bǔ)充的內(nèi)容,我會繼續(xù)補(bǔ)充的;同時也希望大家提出更好的建議。
上一篇:C++選擇排序算法實(shí)例
欄 目:C語言
本文標(biāo)題:C++設(shè)計模式之觀察者模式
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3305.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10APUE筆記之:進(jìn)程環(huá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)存中的存儲方式詳解


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 04-02jquery與jsp,用jquery