企業(yè)加盟網(wǎng)站建設(shè)百家號權(quán)重查詢站長工具
1.定義
????????在GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對觀察者模式是這樣定義的:定義對象的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。當(dāng)一個對象發(fā)生了變化,關(guān)注它的對象就會得到通知;這種交互也成為發(fā)布-訂閱(publish-subscribe)。
2.組成結(jié)構(gòu)
- Subject(目標):目標知道它的觀察者,可以有任意多個觀察者觀察用一個目標,提供注冊和刪除觀察者對象的接口。
- Observer(觀察者):為所有觀察目標的觀察者對象提供一個公共的更新接口。
- ConcreteSubject(具體目標):將有關(guān)狀態(tài)的情況廣播給各ConcreteObserver對象。
- ConcreteObserver(具體觀察者):維護一個指向ConcreteSubject對象的指針,用于當(dāng)具體觀察者初始化時直接存入ConcreteSubject對象(初始化就訂閱ConcreteSubject主題);存儲有有關(guān)狀態(tài),這些狀態(tài)應(yīng)與目標的狀態(tài)保持一致;實現(xiàn)Observer公共更新接口以便使自身狀態(tài)和目標狀態(tài)保持一致。
3.示例代碼
#include <iostream>
#include <list>
using std::cout;
using std::endl;
using std::cin;class Observer
{
public:virtual ~Observer() {};virtual void Update(int) = 0;
};class Subject
{
public:virtual ~Subject() {};virtual void Attach(Observer*) = 0;virtual void Detach(Observer*) = 0;virtual void Notify() = 0;
};class ConcreteObserver : public Observer
{
private:Subject* _pSubject;public:ConcreteObserver(Subject* pSubject) :_pSubject(pSubject){//在目標中注冊當(dāng)前觀察者(此處的觀察者是廣義上的觀察者,目標并不知道具體誰要觀察它,目標只進行廣播即可)this->_pSubject->Attach(this);cout << "I'm the observer \" 1 \".\n";}void Update(int value) override{cout << "ConcreteObserver get the update.New State:" << value << endl;}
};class ConcreteObserver2 : public Observer
{
private:Subject* _pSubject;public:ConcreteObserver2(Subject* pSubject) :_pSubject(pSubject){//在目標中注冊當(dāng)前觀察者(此處的觀察者是廣義上的觀察者,目標并不知道具體誰要觀察它,目標只進行廣播即可)this->_pSubject->Attach(this);cout << "I'm the observer \" 2 \".\n";}void Update(int value) override{cout << "ConcreteObserver2 get the update.New State:" << value << endl;}
};class ConcreteSubject :public Subject
{
private:std::list<Observer*> _pObserverList;int _iState;
public:void SetState(int state){_iState = state;}void Attach(Observer* pObserver) override{_pObserverList.push_back(pObserver);}void Detach(Observer* pObserver) override{_pObserverList.remove(pObserver);}void Notify() override{auto begin = _pObserverList.begin();auto end = _pObserverList.end();while (begin != end){(*begin)->Update(_iState);begin++;}}
};int main()
{//創(chuàng)建目標ConcreteSubject* pSubject = new ConcreteSubject();//創(chuàng)建觀察者Observer* pObserver = new ConcreteObserver(pSubject);Observer* pObserver2 = new ConcreteObserver2(pSubject);//改變當(dāng)前狀態(tài)pSubject->SetState(2);//廣播給所有廣義上的觀察者pSubject->Notify();//去除某個觀察者pSubject->Detach(pObserver);//改變當(dāng)前狀態(tài)pSubject->SetState(3);//重新廣播pSubject->Notify();//結(jié)束,釋放對象delete pObserver;delete pObserver2;delete pSubject;return 0;
}
4.使用說明
意圖:定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都會得到通知并被自動更新。
主要解決:一個對象狀態(tài)改變并給其它對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。
何時使用:一個對象(目標對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進行廣播通知。
如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。
關(guān)鍵代碼:在抽象類里有一個arrayList存放觀察者們。
應(yīng)用實例:1、拍賣的時候,拍賣師觀察最高價格,然后通知給其它競價者競價。2、西游記里面悟空請求菩薩降服紅孩兒,菩薩灑了一地水找來一個老烏龜,這個老烏龜就是觀察者(菩薩是被觀察者),他觀察菩薩這個動作。
優(yōu)點:1、觀察者和被觀察者是抽象耦合的。2、建立一套觸發(fā)機制。
缺點:1、如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。2、如果在觀察者和觀察目標之間有循環(huán)依賴的話,觀察目標會觸發(fā)它們之間進行循環(huán)調(diào)用,可能導(dǎo)致系統(tǒng)崩潰。3、觀察者模式?jīng)]有相應(yīng)的機制讓觀察者知道所觀察的目標對象是怎么發(fā)生變化的,而僅僅只是知道觀察目標發(fā)生了變化。
使用場景:
- 一個抽象模型有兩個方面,其中一個方面發(fā)依賴于另外一個方面。將這些方面封裝在獨立的對象中使它們可以各自獨立地改變和復(fù)用。
- 一個對象的改變將導(dǎo)致其它一個或多個對象發(fā)生改變,而不知道具體有多少對象將發(fā)生改變,可以降低對象之間的耦合度。
- 一個對象必須通知其他對象,而并不知道這些對象是誰。
- 需要在系統(tǒng)中創(chuàng)建一個觸發(fā)鏈,A對象的行為將影響B(tài)對象,B對象的行為將影響C對象……,可以使用觀察者模式創(chuàng)建一種鏈式觸發(fā)機制。
注意事項:1、應(yīng)避免循環(huán)引用。2、如果順序執(zhí)行,某一觀察者錯誤會導(dǎo)致系統(tǒng)卡殼,一般采用異步方式(多線程)。
?
引用
C++觀察者模式_c++ observer-CSDN博客
?