定义:观察者模式(发布/订阅模式,模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式,属于行为模式中的一种,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
当一个对象发生了变化,关注它的对象就会得到通知;这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者。
举例
对同一组数据进行统计分析时候, 我们希望能够提供多种形式的表示 (例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据, 我们当然需要当数据改变的时候, 所有的统计的显示都能够同时改变。
角色
- 抽象主题(Subject):该角色是一个抽象类或接口,定义了增加、删除、通知观察者对象的方法。
- 具体主题(ConcreteSubject):该角色继承或实现了抽象主题,定义了一个集合存入注册过的具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
- 抽象观察者(Observer):该角色是具体观察者的抽象类,定义了一个更新方法。
- 具体观察者(ConcrereObserver):该角色是具体的观察者对象,在得到具体主题更改通知时更新自身的状态。
代码示例:
#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) : m_pSubject(pSubject) {}
void Update(int value)
{
cout << "ConcreteObserver get the update. New State is:" << value << endl;
}
private:
Subject* m_pSubject;
};
class ConcreteObserver2 : public Observer
{
public:
ConcreteObserver2(Subject* pSubject) : m_pSubject(pSubject) {}
void Update(int value)
{
cout << "ConcreteObserver2 get the update. New State is:" << value << endl;
}
private:
Subject* m_pSubject;
};
class ConcreteSubject : public Subject//具体目标
{
public:
void Attach(Observer* pObserver);
void Detach(Observer* pObserver);
void Notify();
void SetState(int state)
{
m_iState = state;
}
private:
list<Observer*> m_ObserverList;
int m_iState;
};
void ConcreteSubject::Attach(Observer* pObserver)//将观察者添加到容器中
{
m_ObserverList.push_back(pObserver);
}
void ConcreteSubject::Detach(Observer* pObserver)//将观察者从容器中删除
{
m_ObserverList.remove(pObserver);
}
void ConcreteSubject::Notify()//通知容器中的每一个观察者
{
std::list<Observer*>::iterator it = m_ObserverList.begin();
while (it != m_ObserverList.end())
{
(*it)->Update(m_iState);
++it;
}
}
int main()
{
ConcreteSubject* pSubject = new ConcreteSubject();//创建具体的目标
Observer* pObserver = new ConcreteObserver(pSubject);//创建观察者对象
Observer* pObserver2 = new ConcreteObserver2(pSubject);//创建观察者对象2
pSubject->SetState(2);//设置目标状态
pSubject->Attach(pObserver);//将观察者注册到容器中
pSubject->Attach(pObserver2);
pSubject->Notify();//通知所有的观察者
pSubject->Detach(pObserver);//删除观察者pObserver
pSubject->SetState(3);//更新目标状态
pSubject->Notify();//再次通知所有的观察者,此时容器中只有观察者pObserver2
delete pObserver;
delete pObserver2;
delete pSubject;
}
具体应用示例
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Subject;
//抽象观察者
class Observer
{
protected:
string name;
Subject* sub;
public:
Observer(string name, Subject* sub)
{
this->name = name;
this->sub = sub;
}
virtual void update() = 0;
};
//具体的观察者,看股票的
class StockObserver :public Observer
{
public:
StockObserver(string name, Subject* sub) :Observer(name, sub)
{
}
void update();
};
//具体的观察者,看NBA的
class NBAObserver :public Observer
{
public:
NBAObserver(string name, Subject* sub) :Observer(name, sub)
{
}
void update();
};
//抽象通知者
class Subject
{
protected:
list<Observer*> observers;
public:
string action;
virtual void attach(Observer*) = 0;
virtual void detach(Observer*) = 0;
virtual void notify() = 0;
};
//具体通知者,秘书
class Secretary :public Subject
{
void attach(Observer* observer)
{
observers.push_back(observer);
}
void detach(Observer* observer)
{
list<Observer*>::iterator iter = observers.begin();
while (iter != observers.end())
{
if ((*iter) == observer)
{
observers.erase(iter);
}
++iter;
}
}
void notify()
{
list<Observer*>::iterator iter = observers.begin();
while (iter != observers.end())
{
(*iter)->update();
++iter;
}
}
};
void StockObserver::update()
{
cout << name << " 收到消息:" << sub->action << endl;
if (sub->action == "领导来了!")
{
cout << "我马上关闭股票,装做很认真工作的样子!" << endl;
}
}
void NBAObserver::update()
{
cout << name << " 收到消息:" << sub->action << endl;
if (sub->action == "领导来了!")
{
cout << "我马上关闭NBA,装做很认真工作的样子!" << endl;
}
}
int main()
{
Subject* se = new Secretary(); //创建观察者 //被观察的对象
Observer* o1= new NBAObserver("zhangsan", se);
Observer* o2 = new NBAObserver("lisi", se);
Observer* lm = new StockObserver("limin", se);
//加入观察队列
se->attach(o1);
se->attach(o2);
se->attach(lm);
//事件
se->action = "去吃饭了!";
se->notify();
cout << endl;
se->action = "领导来了!";
se->notify();
return 0;
}
适用场合
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立的改变和复用。
- 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。也就是说,你不希望这些对象是紧密耦合的。