專業(yè)的移動(dòng)網(wǎng)站建設(shè)公司seo網(wǎng)站推廣多少錢
系列文章目錄
C++技能系列
Linux通信架構(gòu)系列
C++高性能優(yōu)化編程系列
深入理解軟件架構(gòu)設(shè)計(jì)系列
高級(jí)C++并發(fā)線程編程
設(shè)計(jì)模式系列
期待你的關(guān)注哦!!!
現(xiàn)在的一切都是為將來的夢想編織翅膀,讓夢想在現(xiàn)實(shí)中展翅高飛。
Now everything is for the future of dream weaving wings, let the dream fly in reality.
行為型設(shè)計(jì)模式之觀察者模式
- 系列文章目錄
- 一、觀察者模式介紹
- 二、觀察者模式優(yōu)缺點(diǎn)
- 2.1 優(yōu)點(diǎn)
- 2.2 缺點(diǎn)
- 三、觀察者模式使用場景
- 四、觀察者模式實(shí)現(xiàn)
- 4.1 示例1 - 代碼實(shí)現(xiàn)
- 4.1 示例2 - 代碼實(shí)現(xiàn)
一、觀察者模式介紹
?? 意圖:
定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都得到通知并被自動(dòng)更新。
?? 主要解決:
一個(gè)對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。
?? 何時(shí)使用:
一個(gè)對象(目標(biāo)對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進(jìn)行廣播通知。
?? 如何解決:
使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。
觀察者模式(Observer),又叫發(fā)布-訂閱模式(Publish/Subscribe):定義對象間的一種一對多的依賴關(guān)系,當(dāng)一個(gè)對象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對象都要得到通知并自動(dòng)更新。
觀察者模式從根本上講必須包含兩個(gè)角色:觀察者和被觀察對象。
被觀察對象自身應(yīng)該包含一個(gè)容器來存放觀察者對象,當(dāng)被觀察者自身發(fā)生改變時(shí)通知容器內(nèi)所有的觀察者對象自動(dòng)更新。
觀察者對象可以注冊到被觀察者的中,完成注冊后可以檢測被觀察者的變化,接收被觀察者的通知。當(dāng)然觀察者也可以被注銷掉,停止對被觀察者的監(jiān)控。
二、觀察者模式優(yōu)缺點(diǎn)
2.1 優(yōu)點(diǎn)
-
觀察者和被觀察者是抽象耦合的。
-
建立一套觸發(fā)機(jī)制。
2.2 缺點(diǎn)
-
如果一個(gè)被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。
-
如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話,觀察目標(biāo)會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,可能導(dǎo)致系統(tǒng)崩潰。
-
觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對象是怎么發(fā)生變化的,而僅僅只是知道觀察目標(biāo)發(fā)生了變化。
三、觀察者模式使用場景
-
當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一方面。將這二者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立的改變和復(fù)用;
-
當(dāng)對一個(gè)對象的改變需要同時(shí)改變其它對象,而不知道具體有多少對象有待改變;
-
當(dāng)一個(gè)對象必須通知其它對象,而它又不能假定其它對象是誰;也就是說,你不希望這些對象是緊密耦合的。
四、觀察者模式實(shí)現(xiàn)
4.1 示例1 - 代碼實(shí)現(xiàn)
這里的目標(biāo) Subject 提供依賴于它的觀察者 Observer 的注冊( Attach) 和注銷( Detach)操作,并且提供了使得依賴于它的所有觀察者同步的操作( Notify)。 觀察者 Observer 則提供一個(gè) Update 操作, 注意這里的 Observer 的 Update 操作并不在 Observer 改變了 Subject 目標(biāo)狀態(tài)的時(shí)候就對自己進(jìn)行更新, 這個(gè)更新操作要延遲到 Subject 對象發(fā)出 Notify 通知所有Observer 進(jìn)行修改(調(diào)用 Update)。
#include <iostream>
#include <string>
#include <list>
using namespace std;class Subject;
//抽象觀察者
class Observer
{
protected:string name;Subject *sub;
public:Observer(string name, Subject *sub){this->name = name;this->sub = sub;}virtual void update() = 0;
};
//具體的觀察者,看股票的
class StockObserver :public Observer
{
public:StockObserver(string name, Subject *sub) :Observer(name, sub){}void update();
};
//具體的觀察者,看NBA的
class NBAObserver :public Observer
{
public:NBAObserver(string name, Subject *sub) :Observer(name, sub){}void update();
};
//抽象通知者
class Subject
{
protected:list<Observer*> observers;
public:string action;virtual void attach(Observer*) = 0;virtual void detach(Observer*) = 0;virtual void notify() = 0;
};
//具體通知者,秘書
class Secretary :public Subject
{void attach(Observer *observer){observers.push_back(observer);}void detach(Observer *observer){list<Observer *>::iterator iter = observers.begin();while (iter != observers.end()){if ((*iter) == observer){observers.erase(iter);}++iter;}}void notify(){list<Observer *>::iterator iter = observers.begin();while (iter != observers.end()){(*iter)->update();++iter;}}
};void StockObserver::update()
{cout << name << " 收到消息:" << sub->action << endl;if (sub->action == "梁所長來了!"){cout << "我馬上關(guān)閉股票,裝做很認(rèn)真工作的樣子!" << endl;}
}void NBAObserver::update()
{cout << name << " 收到消息:" << sub->action << endl;if (sub->action == "梁所長來了!"){cout << "我馬上關(guān)閉NBA,裝做很認(rèn)真工作的樣子!" << endl;}
}int main()
{Subject *dwq = new Secretary(); //創(chuàng)建觀察者<br> //被觀察的對象Observer *xs = new NBAObserver("xiaoshuai", dwq);Observer *zy = new NBAObserver("zouyue", dwq);Observer *lm = new StockObserver("limin", dwq);//加入觀察隊(duì)列dwq->attach(xs);dwq->attach(zy);dwq->attach(lm);//事件dwq->action = "去吃飯了!";<br> //通知dwq->notify();cout << endl;dwq->action = "梁所長來了!";dwq->notify();return 0;
}
4.1 示例2 - 代碼實(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 SubjectConcreteSubject *pSubject = new ConcreteSubject();// Create ObserverObserver *pObserver = new ConcreteObserver(pSubject);Observer *pObserver2 = new ConcreteObserver2(pSubject);// Change the statepSubject->SetState(2);// Register the observerpSubject->Attach(pObserver);pSubject->Attach(pObserver2);pSubject->Notify();// Unregister the observerpSubject->Detach(pObserver);pSubject->SetState(3);pSubject->Notify();delete pObserver;delete pObserver2;delete pSubject;
}