观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者。
动机
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象的状态改变,所有的依赖对象都得到通知。如果这样的依赖关系过于紧密,将会使软件不能很好地抵御变化。
使用面向对象技术,可以使这种依赖关系弱化,并形成一种稳定的依赖的关系,从而使软件体系更加具有耦合性
角色扮演
抽象主题角色(Subject)
知道它的观察者,可以有任意多个观察者观察同一个目标;提供注册和删除观察者对象的接口
具体主题角色(RealSubject)被观察对象
将有关状态存入各具体观察者对象;当它的状态发生改变时,向它的各个观察者发出通知
抽象观察者(Observer)
为那些在抽象主题发生改变时需获得通知的对象定义一个更新的接口
具体观察者角色(RealObserver、RealObserver1)
维护一个具体主题对象的引用;存储有关状态,这些状态应与抽象主题的状态保持一致;实现Oberver的更新接口以使自身状态与抽象主题的状态保持一致
举例说明
这里我们注册两个观察者,当具体主题有状态变化时,通知观察者,作数据的更新同步
//抽象观察者
class Observer
{
public:
Observer();
virtual ~Observer();
virtual void Update(int) = 0 ;
protected:
private:
};
//具体观察者1
class RealObserver :public Observer
{
public:
RealObserver(){}
virtual ~RealObserver();
void Update(int value){
cout<< "RealObserser get the new value: "<< value <<endl ;
}
protected:
private:
};
//具体观察者2
class RealObserver1 :public Observer
{
public:
RealObserver1(){}
virtual ~RealObserver1();
void Update(int value){
cout<< "RealObserser1 get the new value: "<< value <<endl ;
}
protected:
private:
};
//抽象主题
class Subject
{
public:
Subject();
virtual ~Subject();
virtual void Add(Observer *) = 0; //具有注册观察者的接口
virtual void Del(Observer *) = 0; //具有注销观察者的接口
virtual void Inform() = 0; //具有通知的方法
protected:
private:
};
//具体主题
class RealSubject : public Subject
{
public:
RealSubject();
virtual ~RealSubject();
void Add(Observer* pObserver); //注册观察者具体实现
void Del(Observer *pObserver); //注销观察者的具体实现
void Inform(); //通知的具体实现
void SetState(int state){ //状态改变方法
m_state = state;
}
protected:
private:
std::list<Observer* > m_Observerlist; //声明一个观察者链表引用
int m_state;
};
void RealSubject::Add(Observer* pObserver){
m_Observerlist.push_back(pObserver);
}
void RealSubject::Del(Observer* pObserver){
m_Observerlist.remove(pObserver);
}
void RealSubject::Inform(){
std::list<Observer* >::iterator it = m_Observerlist.begin(); //依次通知
while(it != m_Observerlist.end()){
(*it)->Update(m_state);
++it;
}
}
demo:
int main(){
RealSubject * rsub = new RealSubject(); //创建具体主题
Observer * ob1 = new RealObserver(); //创建观察者
Observer * ob2 = new RealObserver1();
rsub->SetState(10); //改变一数据
rsub->Add(ob1); //观察者注册
rsub->Add(ob2);
rsub->Inform(); //发出通知
rsub->SetState(9); //改变一数据
rsub->Del(ob2); //注销一个观察者
rsub->Inform(); //再次发出通知
return 0;
}
结果:
第一次发出通知前,由于注册了两个观察者,因此两个观察者对象都收到更新数据的通知;而第二次发出通知前,已经有一个观察者退出观察行列,因此只有观察者1收到了通知。
优点
观察者和被观察者是一套触发机制:保证高度的协作;
缺点
观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
应用场景
(1)当一个抽象模型有两个方面,其中一个方面依赖于另一方面,将这二者封装在独立的对象中,以使他们可以独立的改变和复用
(2)当对一个对象的改变需要同时改变其他的对象,而不知道具体有多少对象有待改变
(3)当对一个对象必须通知其他对象,而他不能假定其他对象是谁,也就是说,你不希望这些对象是精密耦合