这几天由于一直在研究智能指针,由weak_ptr解决shared_ptr的循环引用问题得到了weak_ptr是shared_ptr的观察者模式(又称发布-订阅模式)的理论。但是观察者模式是怎么回事呢。先引用一段设计模式的原文:
Intent :
Define a one-to-many dependency between objects so that when oneobject changes state, all its dependents are notified and updated automatically.
即在被观察者和观察者之间定义一个一对多的依赖关系,当被观察者状态改变时,观察者就会被通知并且更新其状态。
Applicability:
应用:
When an abstraction has two aspects, one dependent on the other.Encapsulating these aspects in separate objects lets you vary and reuse them independently.
情况一:有两个事件,一个依赖于另一个,可以分别封装这两个事件以提高变化性和重用性。
When a change to one object requires changing others, and you don't know how many objects need to be changed.
情况二:当一个对象的改变会引起其他的对象的改变,而你又不知道会影响多少个的时候。
When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.
情况三:当一个对象需要通知其他对象而又不想知道他们是谁的时候。换句话说就是不想让这些对象耦合太紧的时候。(个人感觉是跟第二个说的一回事)
下面是官方的UML图:
很常见的例子为天气预报订阅,手机可以订阅某些城市的天气情况,那么手机就是这些地区天气情况的观察者,当天气发生改变时通知到手机,手机再更新本地的天气情况的信息。
下图是我仿写的一个简单的例子来说明。首先给出UML图
:
#ifndef OBSERVER_H
#define OBSERVER_H
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <list>
using namespace std;
using namespace boost;
class IObserver//Observer接口类
{
public:
virtual void UpdateInfo(int id)=0;
};
class ISubject//被观察者Target接口类
{
public:
virtual void Register(shared_ptr<IObserver> observer)=0;
virtual void ObserverRemove(shared_ptr<IObserver> observer)=0;
virtual void Notify()=0;
};
#endif
#include "Observer.h"
using namespace std;
using namespace boost;
class A : public IObserver
{
public:
A(int id):tid(id){}
void UpdateInfo(int id);
private:
int tid;
};
void A::UpdateInfo(int id)
{
cout << id << endl;
}
class D:public ISubject
{
public:
D(int str):id(str){};
void Register(shared_ptr<IObserver> observer);
void ObserverRemove(shared_ptr<IObserver> observer);
void Notify();
private:
list<shared_ptr<IObserver>> ListofObserver;//每个被观察者都有一个存贮观察者的指针的容器。以方便对多个观察者进行通知
int id;
};
void D::Register(shared_ptr<IObserver> observer)//注册函数,用于存贮观察者的指针
{
ListofObserver.push_back(observer);
}
void D::ObserverRemove(shared_ptr<IObserver> observer)//移除函数,用于移除观察者,也就是说被观察者有权解除观察者的观察
{
ListofObserver.remove(observer);
}
void D::Notify()//通知观察者,这里一般都是调用观察者提供的方法,或者返回给观察者一个状态
{
for(list<shared_ptr<IObserver>>::iterator it = ListofObserver.begin();it != ListofObserver.end();++it)
{
(*it)->UpdateInfo(id);
}
}
int main(int,char**)
{
shared_ptr<IObserver> p1(new A(1));//
shared_ptr<IObserver> p2(new A(2));//构建两个观察者
shared_ptr<ISubject> p3(new D(3));//
shared_ptr<ISubject> p4(new D(4));//构建两个被观察者
p3->Register(p1);
p4->Register(p2);//分别注册
p3->Notify();
p4->Notify();//分别通知
}
上面的代码只是表达了两个观察者分别订阅两个被观察者的例子,之所以这个模式被称为订阅-发布模式也是这个道理,由于多态性,发布者不需要知道究竟谁订阅过,只需要在状态改变的时候发布即可,若干订阅者自会收到状态改变的通知的。