观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象,在主题对象的状态发生变化时,会通知所有的观察者。
观察者模式角色如下:
抽象主题(Subject)角色:抽象主题角色提供维护一个观察者对象集合的操作方法,对集合的增加、删除等。
具体主题(ConcreteSubject)角色:将有关状态存入具体的观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发通知。具体主题角色负责实现抽象主题中的方法。
抽象观察者(Observer)角色:为具体观察者提供一个更新接口。
具体观察者(ConcreteObserver)角色:存储与主题相关的自洽状态,实现抽象观察者提供的更新接口。
Case:
在教室里老师还没有来,同学都在干着各的事情,小张正在打游戏,小李正在抄作业....., 现在同学们要求班长当卧底,监视老师,当老师来了通知大家一声。然后打游戏的马上停止,抄作业的也停止。
这里班长相当于是一个通知者, 小张、小李,以及其他同学显然是监听者,他们监听了班长那的消息,一旦老师来了马上采取相关的行动。
首先,先把通知者的行为抽象为一个接口:(subject)
class INotifier
{
public:
virtual void registerListenner(ITeacherListenner *l) =0 ;
virtual void removeListenner(ITeacherListenner *l) =0 ;
virtual void notify() =0 ;
};
第二,然后班长作为一个具体的通知者:(ConcreteSubject)
class MonitorNotifier:public INotifier
{
public:
void registerListenner(ITeacherListenner *l)
{
listenners.push_back(l);
}
void removeListenner(ITeacherListenner *l)
{
list<ITeacherListenner*>::iterator it;
for(it=listenners.begin();it!=listenners.end();it++)
{
if(*it == l)
{
listenners.remove(l);
break;
}
}
}
void notify()
{
list<ITeacherListenner*>::iterator it;
for(it=listenners.begin();it!=listenners.end();it++)
{
(*it)->onTecherComming(mValue;);
}
}
void setValue(int value)
{
mValue = value;
notify();
}
private:
list<ITeacherListenner*> listenners;
int mValue;
};
第三, 定义一个监听者的接口,想要监听老师来了这个消息的同学必须要实现这个接口:
class ITeacherListenner
{
public:
virtual void onTecherComming(int value) = 0;
};
第四,ZhangSan 和 LiSi 监听了老师来了这个接口:
class ZhangSan:public ITeacherListenner
{
public:
void onTecherComming(int value)
{
stopCopyWork(value);
}
void stopCopyWork(int value)
{
cout<<"zhangsan stopCopyWork + "<<value<<endl;
}
};
class LiSi:public ITeacherListenner
{
public:
void onTecherComming(int value)
{
stopPlayGame(value);
}
void stopPlayGame(int value)
{
cout<<"lisi stopPlayGame + "<<value<<endl;
}
};
int main()
{
cout << "Hello World1-------------"<<endl;
MonitorNotifier monitor;
ZhangSan zs;
LiSi ls;
monitor.registerListenner(&zs);
monitor.registerListenner(&ls);
monitor.setValue(1);
cout << "Hello World2-------------"<<endl;
monitor.removeListenner(&ls);
monitor.setValue(2);
return 0;
}
运行结果如下:
Hello World1-------------
zhangsan stopCopyWork + 1
lisi stopPlayGame + 1
Hello World2-------------
zhangsan stopCopyWork + 2
示例2
#include <iostream>
#include <vector>
#include <string>
using namespace std;
///抽象一个Subject主题
///观察者
class Observer {
public:
virtual void update(string m_Temp, string m_Humi) = 0;
protected:
Observer() {}
};
class Subject {
public:
virtual void registerObserver(Observer* pObj)=0;
virtual void removeObserver(Observer* pObj)=0;
virtual void noitfyObserver()=0;
protected:
Subject(){}
};
class WeatherData :public Subject {
public:
WeatherData(string Temp, string Humi) : m_Temp(Temp), m_Humi(Humi) {
}
void registerObserver(Observer* pObj) {
m_observers.push_back(pObj);
}
void removeObserver(Observer* pObj) {
auto iter = find(m_observers.begin(), m_observers.end(), pObj);
if (iter != m_observers.end()) {
m_observers.erase(iter);
}
}
void noitfyObserver() {
//逐个遍历调用Observer的update方法
for (vector<Observer*>::iterator iter = m_observers.begin();iter != m_observers.end();iter++) {
(*iter)->update(m_Temp, m_Humi);
}
}
void setData(string Temp, string Humi) {
m_Temp = Temp;
m_Humi = Humi;
noitfyObserver();
}
private:
vector<Observer*> m_observers;
string m_Temp;//温度
string m_Humi;//湿度
};
//CocreteObserver
class PCDisplay:public Observer {
public:
void update(string m_Temp, string m_Humi) {
cout << "我是PC端的显示GUI,当前的温度为" << m_Temp << "湿度为" << m_Humi << endl;
}
PCDisplay(WeatherData* pWeatherData) {
m_pWeatherData = pWeatherData;
m_pWeatherData->registerObserver(this);
}
private:
WeatherData* m_pWeatherData;
};
class MobileDisplay :public Observer {
public:
void update(string m_Temp, string m_Humi) {
cout << "我是Mobile端的显示GUI,当前的温度为" << m_Temp << "湿度为" << m_Humi << endl;
}
MobileDisplay(WeatherData* pWeatherData) {
m_pWeatherData = pWeatherData;
m_pWeatherData->registerObserver(this);
}
private:
WeatherData* m_pWeatherData;
};
int main(void) {
WeatherData* pWD = new WeatherData("22C", "65%");
PCDisplay* pPCDisplay = new PCDisplay(pWD);
MobileDisplay* pMobile = new MobileDisplay(pWD);
pWD->setData("38C", "55%");
pWD->removeObserver(pMobile);
pWD->setData("31", "44%");
system("pause");
return 0;
}
示例3
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Observer { // 抽象观察者,为所有具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫更新接口
public:
virtual void Update() = 0;
};
class Subject { // 主题或抽象通知者,一般用一个抽象类或者接口实现
private:
list<Observer* > observers;
public:
void Attach(Observer* observer) { observers.push_back(observer); } // 增加观察者
void Detach(Observer* observer) { observers.remove(observer); } // 移除观察者
void Notify() { // 通知
for (auto observer = observers.begin(); observer != observers.end(); observer++) {
(*observer)->Update();
}
}
};
class ConcreteSubject : public Subject { // 具体主题或具体通知者,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发送通知
private:
string subjectState;
public:
string GetState() { return subjectState; }
void SetState(string state) { subjectState = state; }
};
class ConcreteObserver : public Observer { // 具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态相协调
private:
string name;
ConcreteSubject* subject;
string observerState;
public:
ConcreteObserver(ConcreteSubject* s, string n) {
subject = s;
name = n;
}
void Update() {
observerState = subject->GetState();
cout << "observer: " << name << ", its new state is: " << observerState << endl;
}
string GetState() { return observerState; }
void SetState(string state) { observerState = state; }
};
int main() {
ConcreteSubject* s = new ConcreteSubject();
s->SetState("ABC");
ConcreteObserver* ox = new ConcreteObserver(s, "X");
ConcreteObserver* oy = new ConcreteObserver(s, "Y");
ConcreteObserver* oz = new ConcreteObserver(s, "Z");
s->Attach(ox);
s->Attach(oy);
s->Attach(oz);
s->Notify();
// observer: X, its new state is: ABC
// observer: Y, its new state is: ABC
// observer: Z, its new state is: ABC
s->SetState("XYZ");
s->Notify();
// observer: X, its new state is: XYZ
// observer: Y, its new state is: XYZ
// observer: Z, its new state is: XYZ
delete ox;
delete oy;
delete oz;
delete s;
return 0;
}