一、介绍
观察者模式又叫做发布-订阅(Publish/Subscribe)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,是他们能够自动更新自己。
二、代码实现
Subject类,可翻译为主题或抽象通知者
把对观察者的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
// class Observable
class Observabl
{
public:
Observable();
virtual ~Observable();
void NotifyUpdate(int subject);
template<typename T>
void AddObserver(LPCTSTR name, int subject, void (T::*method)(int), T *instance);
void AddObserver(LPCTSTR name, HWND hwnd, int subject, UINT messageId, bool post = true);
void RemoveObserver(LPCTSTR name);
private:
typedef std::list<Observer *> Observers;
Observers observers_;
};
Observer类,抽象观察者
为所有的具体观察者定义了一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口,一般由一个类或者一个接口实现。
class Observer {
public:
Observer(LPCTSTR name, int subject);
virtual ~Observer();
virtual void OnUpdate(int subject) = 0; // 纯虚函数,由子类实现
LPCTSTR GetName() const;
int GetSubject() const;
private
CString name_; // 名字
};
ConcreteSubject,具体主题或具体通知者
将有关状态存入具体观察对象,在具体主题的内部状态发生改变时,给所有登记过的观察者发送通知。
ConcreteObserver类,具体观察者
根据自身的状态和主题的状态相协调。
客户端代码
三、特点
优点:
将一个系统分割成一系列相互协调工作的类有一个很不好的副作用,就是需要维护相关对象之间的一致性。我们不希望为了维护一致性而增加类之间的耦合。观察者模式可以降低这种耦合。
用在什么地方?
当一个对象改变,需要同时改变其他对象,而他不知道具体有多少对象需要改变时;
一个抽象有两个方面,一方面依赖另一方面。
不足:
尽管已经用了依赖-倒转原则,但“抽象通知者”还是依赖“抽象观察者”;
每个具体观察者,想调用的方法不一定是“更新”。
!可以由委托事件技术来解决,但二者各有优缺点。
转自《大话设计模式》