在軟件構建過程中,我們需要爲某些對象建立一種“通知依賴關係” ——一個對象(目標對象)的狀態發生改變,所有的依賴對象(觀察者對象)都將得到通知。如果這樣的依賴關係過於緊密,將使軟件不能很好地抵禦變化。使用面向對象技術,可以將這種依賴關係弱化,並形成一種穩定的依賴關係。從而實現軟件體系結構的鬆耦合。
意圖定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時, 所有依賴於它的對象都得到通知並被自動更新。[GOF 《設計模式》]
特點:
1、 Subject和Observer之間是鬆偶合的,分別可以各自獨立改變。
2、 Subject在發送廣播通知的時候,無須指定具體的Observer,Observer可以自己決定是否要訂閱Subject的通知。
3、 遵守大部分GRASP原則和常用設計原則,高內聚、低偶合。
應用場景:
1、 對一個對象狀態的更新,需要其他對象同步更新,而且其他對象的數量動態可變。
2、 對象僅需要將自己的更新通知給其他對象而不需要知道其他對象的細節。
UML圖
代碼實現
#pragma once
#include <string>
#include <list>
#include "Define.h"
class IObserver;
class ISubject
{
public:
ISubject(void);
virtual ~ISubject(void);
virtual int Attach(IObserver* pObs) = 0;
virtual int Detach(IObserver* pObs) = 0;
virtual int Notify() = 0;
virtual State GetState() = 0;
virtual void SetState(const State& state) = 0;
protected:
typedef std::list<IObserver*> L_OBS;
L_OBS m_obsArray;
};
#pragma once
#include "ISubject.h"
class CSubjectA : public ISubject
{
public:
CSubjectA(void);
virtual ~CSubjectA(void);
virtual int Attach(IObserver* pObs);
virtual int Detach(IObserver* pObs);
virtual int Notify();
virtual State GetState();
virtual void SetState(const State& state);
private:
State m_state;
};
#include "CSubjectA.h"
#include "IObserver.h"
CSubjectA::CSubjectA(void)
{
}
CSubjectA::~CSubjectA(void)
{
if (!m_obsArray.empty())
{
m_obsArray.clear();
L_OBS().swap(m_obsArray);
}
}
int CSubjectA::Attach( IObserver* pObs )
{
m_obsArray.push_back(pObs);
return 0;
}
int CSubjectA::Detach( IObserver* pObs )
{
m_obsArray.remove(pObs);
return 0;
}
int CSubjectA::Notify()
{
L_OBS::iterator it_beg, it_end=m_obsArray.end();
for (it_beg=m_obsArray.begin(); it_beg!=it_end; ++it_beg)
{
(*it_beg)->Update();
}
return 0;
}
State CSubjectA::GetState()
{
return m_state;
}
void CSubjectA::SetState( const State& state )
{
m_state = state;
}
#pragma once
#include "Define.h"
class IObserver
{
public:
IObserver(void);
virtual ~IObserver(void);
virtual int Update() = 0;
};
#pragma once
#include "IObserver.h"
class ISubject;
class CObserveA : public IObserver
{
public:
CObserveA(ISubject* pSubject);
virtual ~CObserveA(void);
virtual int Update();
private:
ISubject* m_pSubject;
};
#include "CObserveA.h"
#include <cstdio>
#include "ISubject.h"
CObserveA::CObserveA(ISubject* pSubject)
:m_pSubject(pSubject)
{
m_pSubject->Attach(this);
}
CObserveA::~CObserveA(void)
{
m_pSubject->Detach(this);
}
int CObserveA::Update()
{
State str = m_pSubject->GetState();
printf("first get: [%s]\n", str.c_str());
return 0;
}
#include "CSubjectA.h"
#include "CObserveA.h"
int main()
{
CSubjectA subA;
CObserveA first(&subA);
subA.SetState("test set state");
subA.Notify();
return 0;
}