观察者模式
观察者模式:定义对象间的一对多的依赖关系,以便
当一个对象(subject)状态发生了变化,所有依赖它的对象
都得到通知并更新;
场景有微信朋友圈,知乎,公众号等;
观察者模式的两种模型
1.推模型
目标对象主动向观察者推送目标的详细信息,不管观察者
是否需要,推送的信息通常是目标对象的全部或部分数据,
相当于广播;
2.目标对象在通知观察者的时候,只传递少量的信息。
如果观察者需要具体的信息,由观察者主动到目标对象中获取,
相当于观察者从目标对象中拉取数据。一般这种模型的实现中
会把目标对象通过update方法传递给观察者,这样观察者需要获取
数据的时候,就可以通过这个引用来获取了。
结构
subject(目标对象)
bool m_stat; //状态
list<Observer*> m_list; //存储观察者对象的列表对象
attach(Observer&);//注册观察者到目标对象中
detach(Observer&);//从目标对象中将观察者分离
notifyObserver(void*arg);//通知所有依赖对象
Observer(观察者)
dosomething(void*arg);//根据目标对象发送的通知做出相应的更新操作
/*
观察者(observer)模式
1.在观察者模式中,观察者需要直接订阅目标事件;在目标发出内容
改变的事件后,直接接收事件并作出响应,对象常是一对多关系;
2.常见场景:各种MVC的框架中,Model的变化通知各种类型的View时几乎都存在这种模式;
3.实现思路:
将问题的职责解耦和,将Observeable(目标)和Observer(观察者)抽象开,分清抽象和实体;
*/
#include <iostream>
#include <list>
using namespace std;
//观察者抽象类
class Observer
{
public:
Observer(){;}
virtual void doSometing(void* parg)=0;
};
//子类继承父类,并重写父类虚函数
class User1:public Observer
{
public:
virtual void doSometing(void* parg)
{
cout<<"User1 do some thing:"<<(char*)parg<<endl;
}
};
//子类继承父类,并重写父类虚函数
class User2:public Observer
{
public:
virtual void doSometing(void* parg)
{
cout<<"User2 do some thing:"<<(char*)parg<<endl;
}
};
//被观察者类
class Observeable
{
public:
Observeable():m_bchange(false){;}
//注册观察者
void Attach(Observer* pob)
{
list<Observer*>::iterator it;
for (it = m_pobs.begin(); it != m_pobs.end(); it++)
{
if ((*it) == pob)
{
return;
}
}
m_pobs.push_back(pob);
}
//分离观察者
void Detach(Observer* pob)
{
if (pob == NULL || m_pobs.empty() == true)
{
return;
}
m_pobs.remove(pob);
}
//分离所有观察者
void DetachAll()
{
if (m_pobs.empty() == true)
{
return;
}
m_pobs.clear();
}
//通知,当状态发生变化后,让迭代器中所有对象都执行成员函数(动态多态,虚函数)
void Notify(void* parg)
{
if (m_bchange == false)
{
return;
}
list<Observer*>::iterator it;
for ( it = m_pobs.begin(); it != m_pobs.end(); it++)
{
(*it)->doSometing(parg);
}
m_bchange = false;
}
protected:
void setchange(string news)
{
m_bchange = true;
Notify((void*)news.c_str());
}
private:
bool m_bchange;
list<Observer*> m_pobs;
};
class CNew:public Observeable
{
public:
void release_new(string str)
{
setchange(str);
}
};
int main()
{
User1 u1;
User2 u2;
CNew cnew;
cnew.Attach(&u1);
cnew.Attach(&u2);
cnew.release_new("hello world");
cnew.DetachAll();
cnew.release_new("hello world");
return 0;
}