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