觀察者模式

#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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章