【概念】
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。相当于邮箱当中的订阅功能。
UML图
抽象主题(Subject):把所有观察者对象的引用保存在列表里,提供注册和删除观察者对象的接口。
抽象观察者(Observer):为那些在目标发生改变时须获得通知的对象定义一个更新接口。
具体主题(Concrete Subject):将有关状态存入具体的观察者对象,当他的状态发生改变时,向他的各个观察者发出通知。
具体观察者(Concrete Observer):具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
【代码】
#include<iostream>
#include<list>
#include<string>
using namespace std;
class Subject;
class Observer
{
public:
virtual ~Observer(){};
Observer(){};
virtual void Update(Subject*)=0;
};
class ConcreateObserverA :public Observer
{
public:
ConcreateObserverA(){};
~ConcreateObserverA(){};
virtual void Update(Subject*);
private:
string m_state;
};
class ConcreateObserverB :public Observer
{
public:
ConcreateObserverB(){};
~ConcreateObserverB(){};
virtual void Update(Subject*);
private:
string m_state;
};
class Subject
{
public:
virtual ~Subject(){};
Subject(){};
virtual void Notify();
virtual void Attach(Observer*);
virtual void Detach(Observer*);
virtual string GetState();
virtual void SetState(string state);
private:
string m_state;
list<Observer*> m_list;
};
class ConcreateSubjectA :public Subject
{
public:
ConcreateSubjectA(){};
~ConcreateSubjectA(){};
};
class ConcreateSubjectB :public Subject
{
ConcreateSubjectB(){};
~ConcreateSubjectB(){};
};
void ConcreateObserverA::Update(Subject* pSubject)
{
this->m_state = pSubject->GetState();
cout << "The ConcreateObserverA is " << m_state << endl;
}
void ConcreateObserverB::Update(Subject* pSubject)
{
this->m_state = pSubject->GetState();
cout << "The ConcreateObserverB is " << m_state << endl;
}
void Subject::Attach(Observer* pObserver)
{
this->m_list.push_back(pObserver);
cout << "Attach an Object\n";
}
void Subject::Detach(Observer* pObserver)
{
list<Observer*>::iterator iter;
iter = find(m_list.begin(), m_list.end(), pObserver);
if (iter != m_list.end())
m_list.erase(iter);
cout << "Detach an Observer\n";
}
void Subject::Notify(){
for (list<Observer*>::iterator iter = m_list.begin(); iter != m_list.end(); iter++)
{
(*iter)->Update(this);
}
}
string Subject::GetState()
{
return this->m_state;
}
void Subject::SetState(string state)
{
m_state = state;
}
int main()
{
Observer* p1 = new ConcreateObserverA();
Observer* p2 = new ConcreateObserverB();
Subject* pSubject = new ConcreateSubjectA();
pSubject->Attach(p1);
pSubject->Attach(p2);
pSubject->SetState("old");
pSubject->Notify();
cout << "---------------" << endl;
pSubject->SetState("new");
pSubject->Detach(p2);
pSubject->Notify();
delete p1,p2,pSubject;
return 0;
}
【优点】
观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体现察者聚集,每一个具体现察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
【缺点】
1.如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者通知到会花费很多的时间。
2.如果在被观察者之间有循环依赖的话,被观察者会触发他们之间的循环调用,导致系统崩溃。
3.如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
4.虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。