介紹
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。 這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。[DP]
- Subject被觀察者
定義被觀察者必須實現的職責,它必須能夠動態地增加、取消觀察者。它一般是抽象類或者是實現類,僅僅完成作爲被觀察者必須實現的職責:管理觀察者並通知觀察者。 - Observer觀察者
觀察者接收到消息後,即進行update(更新方法)操作,對接收到的信息進行處理。 - ConcreteSubject具體的被觀察者
定義被觀察者自己的業務邏輯,同時定義對哪些事件進行通知。 - ConcreteObserver具體的觀察者
每個觀察在接收到消息後的處理反應是不同,各個觀察者有自己的處理邏輯。
優點:觀察者和被觀察者之間是抽象耦合;建立一套觸發機制
應用:關聯行爲場景。需要注意的是,關聯行爲是可拆分的,而不是組合關係;事件多級觸發場景;跨系統的消息交換場景,如消息隊列的處理機制
注意:廣播連,消息最多轉發一次(傳遞兩次)
UML類圖
簡單示例代碼:
#ifndef SIMPLE_OBSERVER_H
#define SIMPLE_OBSERVER_H
#include <iostream>
#include <list>
#include <string>
using namespace std;
/**
* @brief The Observer class
* 抽象觀察者,爲所有的具體觀察者定義一個接口,在得到主題的通知時更新自己。
* 抽象觀察者一般用一個抽象類或者一個接口實現,通常包含一個Update()方法
*/
class Observer
{
public:
virtual void update()
{
cout<<"Observer::update()"<<endl;
}
};
/**
* @brief The Subject class
* 抽象通知者,它把所有對觀察者對象的引用保存在一個聚集裏
*/
class Subject
{
public:
void attach(Observer *ob)
{
m_observers.push_back(ob);
}
void detach(Observer *ob)
{
m_observers.remove(ob);
}
void notify()
{
for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
(*it)->update();
}
}
private:
list<Observer *> m_observers;
};
/**
* @brief The ConcreteSubject class
* 具體通知者
*/
class ConcreteSubject : public Subject
{
public:
//具體被觀察者的狀態
string getSubjectState()
{
return m_subjectState;
}
void setSubjectState(string stateStr)
{
m_subjectState = stateStr;
}
private:
string m_subjectState;
};
/**
* @brief The ConcreteObserver class
* 具體觀察者
*/
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(ConcreteSubject *subject , string name)
{
m_subject = subject;
m_name = name;
}
void update()
{
m_observerState = m_subject->getSubjectState();
cout<<"觀察者:"<<m_name<<"的狀態是:"<<m_observerState<<endl;
}
private:
string m_name ;
string m_observerState;
ConcreteSubject *m_subject;
};
#endif // SIMPLE_OBSERVER_H
調用代碼:
ConcreteSubject *s = new ConcreteSubject;
s->attach(new ConcreteObserver(s , "X"));
s->attach(new ConcreteObserver(s , "Y"));
s->attach(new ConcreteObserver(s , "Z"));
s->setSubjectState("ABC");
s->notify();
s->setSubjectState("BCD");
s->notify();
delete s;
s = nullptr;
《大話設計模式種,公司前臺場景代碼》
#ifndef COMPANY_OBSERVER_H
#define COMPANY_OBSERVER_H
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Subject;
/**
* @brief The Observer class
* 抽象觀察者,爲所有的具體觀察者定義一個接口,在得到主題的通知時更新自己。
* 抽象觀察者一般用一個抽象類或者一個接口實現,通常包含一個Update()方法.
*
* 創建該觀察者同時,提供一個抽象通知者,因爲此時通知者有可能會變。
*/
class Observer
{
public:
Observer(Subject *sub , string name)
{
m_subject = sub;
m_name = name;
}
virtual void update()
{
cout<<"Observer::update()"<<endl;
}
protected:
string m_name ;
Subject *m_subject;
};
/**
* @brief The Subject class
* 抽象通知者,它把所有對觀察者對象的引用保存在一個聚集裏
* 因爲此時的通知者不知是:前臺 還是 老闆
*/
class Subject
{
public:
void virtual attach(Observer *ob) = 0;
void virtual detach(Observer *ob) = 0;
void virtual notify() = 0;
void virtual setAction(string act) = 0;
string virtual getAction() const = 0;
};
/***********************************具體的通知者*****************************************/
/**
* @brief The Boss class
* 具體的通知者:老闆自己回來了,前臺美女不在
*/
class Boss : public Subject
{
public:
void attach(Observer *ob)
{
m_observers.push_back(ob);
}
void detach(Observer *ob)
{
m_observers.remove(ob);
}
void notify()
{
for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
(*it)->update();
}
}
void setAction(string act)
{
m_action = act;
}
string getAction() const
{
return m_action;
}
private:
list<Observer *> m_observers;
string m_action;
};
/**
* @brief The Secretary class
* 具體的通知者:老闆回來了,前臺美女在
*/
class Secretary : public Subject
{
public:
void attach(Observer *ob)
{
m_observers.push_back(ob);
}
void detach(Observer *ob)
{
m_observers.remove(ob);
}
void notify()
{
for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
(*it)->update();
}
}
void setAction(string act)
{
m_action = act;
}
string getAction() const
{
return m_action;
}
private:
list<Observer *> m_observers;
string m_action;
};
/***********************************具體的觀察者******************************************/
/**
* @brief The StockObserver class
* 具體的觀察者:看股票的同事
*/
class StockObserver : public Observer
{
public:
StockObserver(Subject *sub , string name )
:Observer(sub , name)
{
}
void update() override
{
cout<<m_subject->getAction()<<" "<<m_name<<" 關閉股票軟件,繼續工作。\n";
}
};
/**
* @brief The GameObserver class
* 具體的觀察者:玩遊戲的同事
*/
class GameObserver : public Observer
{
public:
GameObserver(Subject *sub , string name )
:Observer(sub , name)
{
}
void update() override
{
cout<<m_subject->getAction()<<" "<<m_name<<" 停止玩遊戲,繼續工作。\n";
}
};
/**
* @brief The NBAObserver class
* 具體的觀察者:看NBA的同事
*/
class NBAObserver : public Observer
{
public:
NBAObserver(Subject *sub , string name )
:Observer(sub , name)
{
}
void update() override
{
cout<<m_subject->getAction()<<" "<<m_name<<" 停止觀看NBA,繼續工作。\n";
}
};
#endif // COMPANY_OBSERVER_H
調用代碼:
/*
//具體的通知者
Boss *pHuhansan = new Boss;
//老闆回來,前臺不在
//看股票的同事
StockObserver *pSo = new StockObserver( pHuhansan , "易小天");
//看NBA的同事
NBAObserver *pNo = new NBAObserver(pHuhansan , "趙高");
//玩遊戲的同事
GameObserver *pGo = new GameObserver(pHuhansan , "項羽");
//老闆添加觀察者
pHuhansan->attach(pSo);
pHuhansan->attach(pNo);
pHuhansan->attach(pGo);
pHuhansan->setAction("胡漢三我回來了");
pHuhansan->notify();
*/
//老闆回來,前臺在
Secretary *pMeimei = new Secretary;
//看股票的同事
StockObserver *pSo = new StockObserver( pMeimei , "易小天");
//看NBA的同事
NBAObserver *pNo = new NBAObserver(pMeimei , "趙高");
//玩遊戲的同事
GameObserver *pGo = new GameObserver(pMeimei , "項羽");
//前臺添加觀察者,關係不好的不讓加
pMeimei->attach(pSo);
pMeimei->attach(pNo);
pMeimei->attach(pGo);
pMeimei->setAction("胡漢三大佬回來啦啦啦~~~");
pMeimei->notify();
隨着對該模式理解的深入,會隨時更新該篇博客。
部分內容摘自網絡,若有侵權,聯繫刪除。