#include <iostream>
#include <set>
using namespace std;
/*
obsever模式要解決的問題爲:建立一個一(subject)對多(observer)的依賴關係,並且做到當“一”變化的時候,依賴這個一的“多”也能做到同步改變。
在GOF的《設計模式:可複用面向對象軟件的基礎》一書中對觀察者模式是這樣說的:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。當一個對象發生了變化,關注它的對象就會得到通知;這種交互也稱爲發佈-訂閱(publish-subscribe)。目標是通知的發佈者,它發出通知時並不需要知道誰是它的觀察者。
觀察者模式最常見的一個例子:
對同一組數據可能有多個不同樣式的顯示,例如有表格統計樣式顯示,以柱狀圖樣式顯示,以百分比樣式進行顯示,那麼當數據源有更新的時候,應該做到所有樣式的顯示都能同步更新顯示,觀察者模式就解決了這一個問題。
在以下任一情況下都可以使用觀察者模式:
當一個抽象模型有兩個方面,其中一個方面依賴於另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立的改變和複用;
當對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變;
當一個對象必須通知其它對象,而它又不能假定其它對象是誰;也就是說,你不希望這些對象是緊密耦合的。
Subject(目標)
——目標知道它的觀察者。可以有任意多個觀察者觀察同一個目標;
——提供註冊和刪除觀察者對象的接口。
Observer(觀察者)
——爲那些在目標發生改變時需獲得通知的對象定義一個更新接口。
ConcreteSubject(具體目標)
——將有關狀態存入各ConcreteObserver對象;
——當它的狀態發生改變時,向它的各個觀察者發出通知。
ConcreteObserver(具體觀察者)
——維護一個指向ConcreteSubject對象的引用;
——存儲有關狀態,這些狀態應與目標的狀態保持一致;
——實現Observer的更新接口以使自身狀態與目標的狀態保持一致。
觀察者模式按照以下方式進行協作:
當ConcreteSubject發生任何可能導致其觀察者與其本身狀態不一致的改變時,它將通知它的各個觀察者;
在得到一個具體目標的改變通知後,ConcreteObserver對象可向目標對象查詢信息。ConcreteObserver使用這些信息以使它的狀態與目標對象的狀態一致。
*/
//觀察者的抽象類
class Observer
{
public:
virtual void Update(int state) = 0;
};
//目標的抽象類
class Subject
{
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;
};
//具體的觀察者A
class ConCreteObserverA:public Observer
{
public:
ConCreteObserverA(Subject* pSubject) :m_pSubject(pSubject) {}
void Update(int state)
{
cout << "ConcreteObserverA:" << state << endl;
}
private:
Subject* m_pSubject;
};
//具體的觀察者B
class ConcreteObserverB :public Observer
{
public:
ConcreteObserverB(Subject* pSubject) :m_pSubject(pSubject) {}
void Update(int state)
{
cout << "ConcreteObserverB:" << state << endl;
}
private:
Subject* m_pSubject;
};
//具體的目標
class ConcreteSubject :public Subject
{
public:
ConcreteSubject() :m_iState(0)
{
m_observerSet.clear();
}
void Attach(Observer* pObserver);
void Detach(Observer* pObserver);
void Notify();
void SetState(int iState);
private:
set<Observer*> m_observerSet;
int m_iState;
};
void ConcreteSubject::Attach(Observer* pObserver)
{
m_observerSet.insert(pObserver);
}
void ConcreteSubject::Detach(Observer* pObserver)
{
if (m_observerSet.find(pObserver) != m_observerSet.end())
{
m_observerSet.erase(pObserver);
}
}
void ConcreteSubject::Notify()
{
for (auto& obj : m_observerSet)
{
obj->Update(m_iState);
}
}
void ConcreteSubject::SetState(int iState)
{
m_iState = iState;
}
int main()
{
//目標對象
ConcreteSubject* pSubject = new ConcreteSubject();
//觀察者A和B
Observer* pObserverA = new ConCreteObserverA(pSubject);
Observer* pObserverB = new ConcreteObserverB(pSubject);
pSubject->Attach(pObserverA);
pSubject->Attach(pObserverB);
pSubject->Notify();
//改變目標的狀態之後
cout << "改變目標狀態之後" << endl;
pSubject->SetState(1);
pSubject->Notify();
//刪除一個觀察者之後
cout << "刪除一個觀察者" << endl;
pSubject->Detach(pObserverA);
pSubject->Notify();
system("pause");
return 0;
}