设计模式--观察者模式
设计模式 -- Observer 观察者模式
模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
——《设计模式》GoF
动机(Motivation)
- 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关
系” ——一个对象(目标对象)的状态发生改变,所有的依赖对
象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,
将使软件不能很好地抵御变化。 - 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定
的依赖关系。从而实现软件体系结构的松耦合。
结构(Structure)
要点总结
- 使用面向对象的抽象,Observer模式使得我们可以独立地改变目
标与观察者,从而使二者之间的依赖关系达致松耦合。 - 目标发送通知时,无需指定观察者,通知(可以携带通知信息作
为参数)会自动传播。 - 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
- Observer模式是基于事件的UI框架中非常常用的设计模式,也是
MVC模式的一个重要组成部分。
实战代码
#include <iostream>
#include <list>
#include <string>
/*
观察者模式
定义对象间的一种一对多(变化)的依赖关系,以便当一个
对象(Subject)的状态发生改变时,所有依赖于它的对象都
得到通知并自动更新。
——《设计模式》GoF
*/
using namespace std;
class Observer
{
public:
Observer() { ; }
virtual ~Observer() { ; }
// 当被观察对象发生变化时,通知被观察者调用这个方法
virtual void Update(void* pArg) = 0;
};
class User1 : public Observer
{
public:
virtual void Update(void* pArg)
{
cout << "User1:" << (char *)pArg << endl;
}
};
class User2 : public Observer
{
public:
virtual void Update(void* pArg)
{
cout << "User2:" << (char *)pArg << endl;
//reinterpret_cast
}
};
class Observerable
{
public:
Observerable() :_bChange(false)
{
}
virtual ~Observerable() {}
// 注册观察者
void Attach(Observer* pOb)
{
_Obs.push_back(pOb);
}
// 反注册观察者
void Detach(Observer* pOb)
{
_Obs.remove(pOb);
}
int GetObseverCount() const
{
return _Obs.size();
}
void DetachAll()
{
_Obs.clear();
}
virtual void GetSomeNews(string str)
{
SetChange(str);
}
protected:
void SetChange(string news) // 有变化,需要通知
{
_bChange = true;
Notify((void*)news.c_str());
}
private:
void Notify(void* pArg)
{
if (_bChange == false) return;
//遍历容器
for (auto itr = _Obs.begin(); itr != _Obs.end(); itr++)
(*itr)->Update(pArg);//遍历调用list容器里面子类的虚函数Update,实现各个子类的运行多态
_bChange = false;
}
private:
bool _bChange;
list<Observer*> _Obs;
};
class News : public Observerable
{
public:
virtual void GetSomeNews(string str)
{
SetChange("News: " + str);
}
};
int main()
{
User1 u1;
User2 u2;
News n1;
n1.GetSomeNews("T0");//发送广播
cout << n1.GetObseverCount() << endl; // 0
n1.Attach(&u1);
n1.Attach(&u2);
n1.GetSomeNews("T1");
cout << n1.GetObseverCount() << endl; // 2
n1.Detach(&u2);
n1.GetSomeNews("T2");
cout << n1.GetObseverCount() << endl; // 1
n1.DetachAll();
n1.GetSomeNews("T3");
cout << n1.GetObseverCount() << endl; // 0
return 0;
}
运行结果