【重读设计模式】观察者模式

观察者模式是一个最常见的模式,常见到很多人都使用了很多年都没有觉得他是一个模式(因为太容易想到了)而至于看完这个模式之后才恍然大悟的说,原来这个就是观察者模式。所以观察者那个模式,和现实世界中一样,如果一个对象需要知道另外一个对象的状态是否发生变更,有两种方法,第一种就是不断的来询问(查询),查看当前的状态和之前的状态是不是一致,另外一种就是你只需要告诉我,你关注我了,那么当我的状态发生变化的时候,我再通知你,而无需你一致来查询我的状态。而观察者模式就是实现这种情况的方案。


定义:定义了对象和对象之间一对多的依赖关系,这样一来,当一个对象的状态改变时,它的所有依赖者都会收到通知并自动更新

适用场景:
1.一个对象对另外一个对象的状态有依赖。
2.对依赖会对该对象的行为产生影响。
例子:可使用观察者模式的例子实在是太多,比如一般的系统都会有配置,而系统的行为很多时候依赖于配置,比如数据库配置,其他服务的配置,日志文件路径配置,甚至于业务的配置。而每一项都需要单独的类(甚至很多类)来实现,比如数据库操作类依赖于数据库配置,日志操作类依赖于日志配置等。
设计:将所有的配置通过一个配置管理类来管理,负责配置的定时加载,更新等,通过观察者模式,所有的依赖于配置的都成为配置管理类的观察者,这样当配置发生变更时,配置管理类首先知道发生了变更,他就会将变更的通知发给所有的观察者。这样观察者只需要实现自己的update接口就行,也无需知道配置会什么时候发生变更。
类图:

类实现:
#include <iostream>
using namespace std;


//配置文件内容
struct CONF_CONTENT_STR
{
string file_name;
map<string, string> cfg_items_map;
};


//定义观察者基类
class CObserver
{
public:
int update(CONF_CONTENT_STR& cfg_obj) = 0;
};


//观察者A类
class CObServerA : public CObserver
{
public:
int update(CONF_CONTENT_STR& cfg_obj)
{
m_fielda = atoi(cfg_obj.cfg_items_map["field_a"]);
return 0;
}
private:
int m_fielda;
};


//观察者B类
class CObserverB : public CObserver
{
public:
int update(CONF_CONTENT_STR& cfg_obj)
{
m_fieldb = atoi(cfg_obj.cfg_items_map["field_b"]);
}
private:
int m_fieldb;
};


//主题类,配置文件管理
class CConfMgr
{
public:
int register_observer(CObserver* obj)
{
m_observer_list.push_back(obj);
return 0;
}
int remove_observer(CObserver* obj)
{
vector<CObserver* >::iterator it = find(m_observer_list.begin(), m_observer_list.end(), obj);
if(it != m_observer_list.end())
{
m_observer_list.erase(it);
}


return 0;
}
int notify_observer()
{
vector<CObserver* >::iterator it = m_observer_list.begin();
for(; it!=m_observer_list.end(); ++it)
{
it->update();
}
}


int reload_cfg()
{
printf("重读配置文件并初始化到m_cfg_obj.\n");
notify_observer();//更新了的话,就通知观察者
return 0;
}


private:
vector<CObserver* > m_observer_list;
CONF_CONTENT_STR m_cfg_obj;
};




int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!


//初始化一个CConfMgr
CConfMgr cfg_mgr;
//你要先来注册,我才能通知你哦。
CObserver* oba = new CObServerA;
cfg_mgr.register_observer(oba);


CObserver* obb = new CObServerB;
cfg_mgr.register_observer(obb);


//读取配置
cfg_mgr.reload_cfg();


//中间可以很多位置修改了配置文件
....


//从新加载,并reload
cfg_mgr.reload_cfg();




return 0;
}

总结,再回过头来看观察者模式,该模式缺失没有什么高深的道理,是一个非常简单的模式,但是却非常实用,在一种简单的情况下,也有不使用该模式而使用全局或者静态变量实现的方案,比如,这里例子中的配置,所有的对象都不保存自己的状态(保存也可以),而每次使用时都使用全局或者静态变量中的值,这样确实可以解决部分问题(状态发生了变化他知道)。但这么做有两个不好的点:第一破坏了类的封装性,全局变量或者public静态变量所有人可见本身就破坏了封装性,让类的扩展性变得不好。第二不能做到更新时才通知,观察者模式可以让观察者在主题的状态发生变更时才通知,平时是不通知的。也就是观察者是不知道有主题这个对象存在的,而每次都获取主题的状态就让观察者和主题产生了强依赖,甚至于影响了系统的性能和可以扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值