1.意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
2.动机
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维持一致性而使得各类紧密耦合,因为这样降低了它们的可重用性。
举个例子,一个表格对象和一个柱状图对象还有一个饼图对象,可以描述同一个数据对象,所以当数据对象改变的时候,以上这三个对象也应当同时更新。
3.结构与参与者
4.效果
观察者模式允许你独立地改变目标和观察者。你可以单独复用目标对象而无需同时复用其观察者,反之亦然。它也使你可以在不改动目标和其他的观察者的前提下增加观察者。
1)目标和观察者之间的抽象耦合
因为目标和观察者不是紧密耦合的,它们可以属于一个系统中的不同抽象层次。
2)支持广播通信
3)意外的更新(缺)
因为一个观察者并不知道其他观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常很难捕捉。
简单的更新协议不提供具体细节说明目标中什么被改变了,这就使得上述问题更加严重。
5.实现
6.代码示例
![](https://img-my.csdn.net/uploads/201303/08/1362726628_8623.jpg)
例:
#include <string>
#include <iostream>
#include <vector>
using namespace std;
class SecretaryBase;
//抽象观察者
class CObserverBase
{
protected:
string name;
SecretaryBase* sub;
public:
CObserverBase(string strname,SecretaryBase* strsub)
{
name=strname;
sub=strsub;
}
virtual void Update()=0;
};
//具体的观察者,看股票的
class StockObserver : public CObserverBase
{
public:
StockObserver(string strname,SecretaryBase* strsub) : CObserverBase(strname,strsub)
{
}
virtual void Update();
};
//具体观察者,看NBA的
class NBAObserver : public CObserverBase
{
public:
NBAObserver(string strname,SecretaryBase* strsub) : CObserverBase(strname,strsub){}
virtual void Update();
};
//抽象通知者
class SecretaryBase
{
public:
string action;
vector<CObserverBase*> observers;
public:
virtual void Attach(CObserverBase* observer)=0;
virtual void Notify()=0;
};
//具体通知者
class Secretary :public SecretaryBase
{
public:
void Attach(CObserverBase* ob)
{
observers.push_back(ob);
}
void Notify()
{
vector<CObserverBase*>::iterator p = observers.begin();
while (p!=observers.end())
{
(*p)->Update();
p++;
}
}
};
void StockObserver::Update()
{
cout<<name<<":"<<sub->action<<",不要玩股票了,要开始工作了"<<endl;
}
void NBAObserver::Update()
{
cout<<name<<":"<<sub->action<<",不要看NBA了,老板来了"<<endl;
}
客户端:
int main()
{
SecretaryBase *p=new Secretary(); //创建观察者
//被观察的对象
CObserverBase *s1= new NBAObserver("小李",p);
CObserverBase *s2 = new StockObserver("小赵",p);
//加入观察队列
p->Attach(s1);
p->Attach(s2);
//事件
p->action="老板来了";
//通知
p->Notify();
return 0;
}