一、描述
Observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。JDK里提供的observer设计模式的实现由java.util.Observable类和 java.util.Observer接口组成。从名字上可以清楚的看出两者在Observer 设计模式中分别扮演的角色:Observer是观察者角色,Observable是被观察目标(subject)角色。
最常用的一个例子是:对同一组数据进行统计分析的时候,我们希望能够提供多种形式的表示(例如一表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,当数据发生变化的时候,所有的统计的显示都能够同时改变。Observer模式就是解决这类问题的。
二、结构图
1、抽象主题(Subject)角色:主题角色把所有对观察考对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主题角色又叫做抽象被观察者(Observable)角色,一般用一个抽象类或者一个接口实现。
2、抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
3、具体主题(ConcreteSubject)角色:将有关状态存入具体现察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者角色(Concrete Observable)。具体主题角色通常用一个具体子类实现。
4、具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体现察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
从具体主题角色指向抽象观察者角色的合成关系,代表具体主题对象可以有任意多个对抽象观察者对象的引用。之所以使用抽象观察者而不是具体观察者,意味着主题对象不需要知道引用了哪些ConcreteObserver类型,而只知道抽象Observer类型。这就使得具体主题对象可以动态地维护一系列的对观察者对象的引用,并在需要的时候调用每一个观察者共有的Update()方法。这种做法叫做"针对抽象编程"。
三、代码
#include <list>
#include <string>
#include <cassert>
using namespace std;
class Observer
{
public:
virtual ~Observer(void) { }
virtual void Update() = 0;
};
class Subject
{
public:
Subject() { }
virtual ~Subject() { }
// 增加一个观察者
void Attach(Observer* observer) { m_ObserverList.push_back(observer); }
// 删除一个观察者
void Detach(Observer* observer)
{
std::list<Observer*>::iterator iter;
for (iter = m_ObserverList.begin();
iter != m_ObserverList.end(); ++iter)
{
if (*iter == observer)
{
m_ObserverList.erase(iter);
break;
}
}
}
// 更新信息
void Notify()
{
Observer* observer = NULL;
std::list<Observer*>::iterator iter;
for (iter = m_ObserverList.begin();
iter != m_ObserverList.end(); ++iter)
{
observer = *iter;
if (observer != NULL) observer->Update();
}
}
private:
std::list<Observer*> m_ObserverList;
};
class ConcreteSubject : public Subject
{
public:
ConcreteSubject() { }
~ConcreteSubject() { }
public:
// 接口函数,可以有不同的接口函数
string GetState() const { return m_SubjectState; }
void SetState(const string& state) { m_SubjectState = state; }
private:
string m_SubjectState;
};
// 和ConcreteSubject配套使用的
class ConcreteObserver : public Observer
{
public:
ConcreteObserver(const string& name, ConcreteSubject* subject)
: m_name(name), m_pSubject(subject) { assert(subject != NULL); }
~ConcreteObserver() { }
public:
virtual void Update()
{
assert(m_pSubject != NULL);
m_ObServerState = m_pSubject->GetState();
printf("name:%s, state: %s \n", m_name.c_str(), m_ObServerState.c_str());
}
private:
string m_name;
string m_ObServerState;
ConcreteSubject* m_pSubject;
};
Demo代码
void ObserverDemo()
{
ConcreteSubject* pSubject = new ConcreteSubject();
ConcreteObserver* observer1 = new ConcreteObserver("1111", pSubject);
ConcreteObserver* observer2 = new ConcreteObserver("2222", pSubject);
ConcreteObserver* observer3 = new ConcreteObserver("3333", pSubject);
pSubject->Attach(observer1);
pSubject->Attach(observer2);
pSubject->Attach(observer3);
pSubject->SetState("state11111");
pSubject->Notify();
pSubject->Detach(observer1);
pSubject->SetState("state22222");
pSubject->Notify();
delete pSubject;
delete observer1;
delete observer2;
delete observer3;
}