定义
- 观察者模式,也叫发布-订阅模式,行为型模式的一种,定义了一种一对多的关系,让多个观察者同时监听一个主题对象。主题对象变化时会知会所有对应的观察者通知其更新。
- 观察者模式是应用最多最广的模式之一,MVC就是其典型代表,其实现了业务逻辑(contral)和表现层(view)的解耦。它要解决的问题是建立一个一对多的依赖关系,当这个“一”改变时,依赖这个“一”的“多”也能够随之变化。
C++ DEMO实现
#include<iostream>
#include<list>
using namespace std;
class Observer{
public:
virtual void Update(int) = 0;
};
class Subject{
public:
virtual void Attach(Observer *) = 0;
virtual void Detach(Observer *) = 0;
virtual void Notify() = 0;
};
class ConcreteObserver:public Observer{
public:
ConcreteObserver(Subject *pSubject):obSubject(pSubject){}
void Update(int value){
cout<<"ConcreteObserver object get update,update value:"<<value<<endl;
}
private:
Subject *obSubject;
};
class ConcreteObserver2:public Observer{
public:
ConcreteObserver2(Subject *pSubject):obSubject(pSubject){}
void Update(int value){
cout<<"ConcreteObserver2 object get update,update value:"<<value<<endl;
}
private:
Subject *obSubject;
};
class ConcreteSubject:public Subject{
public:
void Attach(Observer *pObserver){
observerList.push_back(pObserver);
}
void Detach(Observer *pObserver){
observerList.remove(pObserver);
}
void Notify(){
std:list<Observer *>::iterator it = observerList.begin();
while(it != observerList.end()){
(*it)->Update(subjectState);
it++;
}
}
void SetState(int state){
this->subjectState = state;
}
private:
std::list<Observer*> observerList;
int subjectState;
};
int main(){
ConcreteSubject *pSubject= new ConcreteSubject();
Observer *pObserver = new ConcreteObserver(pSubject);
Observer *pObserver2 = new ConcreteObserver2(pSubject);
pSubject->Attach(pObserver);
pSubject->Attach(pObserver2);
pSubject->SetState(10);
pSubject->Notify();
pSubject->Detach(pObserver);
pSubject->SetState(20);
pSubject->Notify();
delete pObserver;
delete pObserver2;
delete pSubject;
system("pause");
return 0;
}
结果如图:

一点想法
- 发布者提供Attach和Detach来注册/注销对应订阅者,自身有对应的状态改变接口(SetState),发布者状态更新后会知会各个订阅者进行更新(Nodify->Update)
- demo里的数据结构用的list,一个原因是动态长度,还有是这块主要涉及增删操作,链表更为合适。
- 优点
– 发布者只知道订阅者的一个列表,两者间只有一个共同的接口。
– 发布者和订阅者解耦
– 发布者可以广播消息 - 缺点
– 发布者通知订阅者需要遍历整个链表来通知,时间可能过长
– 可能会出现循环依赖导致死循环的问题
– 订阅者不知道发布者是怎么变化的