设计模式C++描述----04.观察者(Observer)模式
一. 概述
Observer 模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。
Sbuject 相当于通知者,它提供依赖于它的观察者Observer 的注册(Attach)和注销(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。
Observer 相当于观察者,则提供一个Update操作,注意这里的 Observer 的 Update 操作并不在Observer 改变了Subject目标状态的时候就对自己进行更新,这个更新操作要延迟到 Subject 对象发出 Notify 通知所有 Observer 进行修改(调用Update)。
二. 举例
最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。
结构关系图如下:
DataSubject : 我们就认为是原始数据。
SheetObserver:就认为是表格,用来显示原始数据用的。
ChartObserver :就认为是图表,也是来显示原始数据的。
代码如下:
[cpp] //////////////////////////////////////////////////////////////////////////
//观察者基类
class Observer
{
public:
virtual ~Observer()
{
}
virtual void Update(Subject* sub) = 0;
virtual void PrintInfo() = 0;
protected:
Observer()
{
_st = '\0';
}
string _st;
};
//////////////////////////////////////////////////////////////////////////
//通知者基类
class Subject
{
public:
virtual ~Subject()
{
}
//注册观察者,这样通知者就能通知到观察者
virtual void Attach(Observer* obv)
{
_obvs->push_front(obv);
}
//注销观察者,通知者不再通知观察者
virtual void Detach(Observer* obv)
{
if (obv != NULL)
_obvs->remove(obv);
}
//通知操作,通知后对于每个注册过的观察者,将会调用自己的update方法
virtual void Notify()
{
list<Observer*>::iterator it;
it = _obvs->begin();
for (;it != _obvs->end();it++)
{
(*it)->Update(this);
}
}
virtual void SetState(const string& st) = 0;
virtual string GetState() = 0;
protected:
Subject()
{
_obvs = new list<Observer*>;
}
private:
list<Observer* >* _obvs;
};
//////////////////////////////////////////////////////////////////////////
//具体的数据通知者
class DataSubject:public Subject
{
public:
DataSubject()
{
_st = '\0';
}
~DataSubject()
{
}
//自己的状态
string GetState()
{
return _st;
}
void SetState(const string& st)
{
_st = st;
}
private:
string _st;
};
//////////////////////////////////////////////////////////////////////////
//数据表格观察者
class SheetObserver:public Observer
{
public:
virtual Subject* GetSubject()
{
return _sub;
}
//构造函数里,把自己注册到通知者里
SheetObserver(Subject* sub)
{
_sub = sub;
_sub->Attach(this);
}
virtual ~SheetObserver()
{
_sub->Detach(this);
if (_sub != 0)
delete _sub;
}
//更新操作
void Update(Subject* sub)
{
_st = sub->GetState(); //具体的数据可以从Subject这个通知者中取
PrintInfo();
}
void PrintInfo()
{
cout<<"Sheet observer.... "<<_sub->GetState()<<endl;
}
private:
Subject* _sub;
};
//数据图表观察者
class ChatObserver:public Observer
{
public:
virtual Subject* GetSubject()
{
补充:软件开发 , C++ ,