您的位置:首页 > 其它

9.观察者模式

2015-06-11 17:19 106 查看
1.说明

请参阅该系列第一篇文章。

2.观察者模式说明

观察者模式:定义了一种一对多的关系,让多个观察者对象监听某一主题对象,这个主体对象发生改变时,会通知观察者对象,使他能够自动更新自己

特点:将一个系统分割成一系列相互协作的类是一个很不好的副作用,那就是需要维护相关对象的一致性,我们不希望为了维护类的一致性而使类紧密耦合,这样会给维护,扩展,重用带来很多不便。

使用场景:当一个对象的改变需要需要同时改变其他对象,而且他不知道有多少个对象需要改变,这个时候就应该使用观察者模式,发出通知即可

作用:解除类之间的耦合,让耦合的双方都依赖于抽象,而不是具体的。

另外一种重要的方式:使用委托(待看)

委托对象所搭载的方式,必须具备于原来的有相同的形式,参数列表,返回值类型

公司项目就是通过观察者模式构建的,要扩展的时候,直接进行挂载,感觉很方便

3.UML



4.代码

代码背景:

在一个公司中,有老板,leader,员工A,B。老板管理leader,A,B。Leader管理A,B。A,B的上级有leader,老板,当其中任意一个对象状态发生改变,A,B状态也发生改变。在真正的项目中可能不会这么复杂,此处只是模拟现实中状况

//观察者基类
#ifndef __SUBJECT_H
#define __SUBJECT_H

#include <iostream>
#include <list>
#include "Observer.h"

class CSubject
{
public:
void add(CObserver* obser)
{
m_objlist.push_back(obser);
}
void del(CObserver* obser)
{
for (std::list<CObserver*>::iterator it=m_objlist.begin(); it!=m_objlist.end(); it++)
{
if ((*it)->getname() == obser->getname())
{
m_objlist.erase(it);
break;
}
}
}
void notify()
{
for (std::list<CObserver*>::iterator it=m_objlist.begin(); it!=m_objlist.end(); it++)
{
(*it)->notify();
}
}
virtual std::string get_subject_status() = 0;

virtual int get_subflag() = 0;

private:
std::list<CObserver*> m_objlist;
};

#endif

//观察者 大boss
#ifndef __BIGBOSS_H
#define __BIGBOSS_H

#include "Subject.h"

class CBigBoss:public CSubject
{
public:
CBigBoss(std::string name)
{
m_flag = 0;
m_name = name;
}
std::string get_subject_status()
{
return "BigBoss BACK";
}
void action()
{
m_flag = 1;
notify();
m_flag = 0;
}
int get_subflag()
{
return m_flag;
}
private:
std::string m_name;
int m_flag;
};

#endif

//即是观察者也是统治者的 TM leader
#ifndef __BOSS_H
#define __BOSS_H

#include "Subject.h"
#include "Observer.h"

class CBoss:public CSubject,public CObserver
{
public:
CBoss(std::string name)
{
m_flag = 0;
m_name = name;
}
std::string get_subject_status()
{
return "TM Leader BACK";
}
void action()
{
m_flag = 1;
notify(1);
m_flag = 0;
}
int get_subflag()
{
return m_flag;
}
std::string getname()
{
return m_name;
}

public:
void add_sub(CSubject* ober)
{
m_sublist.push_back(ober);
}
void notify(int x)
{
CSubject::notify();
}
void notify()
{
//大老板发通知后,拍着马屁也发通知
std::cout<<"I recved big boss notify"<<std::endl;
CSubject::notify();
for (std::list<CSubject*>::iterator it=m_sublist.begin(); it!=m_sublist.end(); it++)
{
if ((*it)->get_subflag())
{
std::cout<<(*it)->get_subject_status()<<"  "<<m_name.c_str()<<"  赶快努力工作"<<std::endl;
}
}
}

private:
std::list<CSubject*> m_sublist;
std::string m_name;
int m_flag;
};

#endif

//通知者基类

#ifndef __OBSERVER_H
#define __OBSERVER_H

//存在互相依赖,为了方便直接注释掉
//#include "Subject.h"
#include <iostream>
#include <string>

class CObserver
{
public:
virtual void notify() = 0;
virtual std::string getname() = 0;

//virtual void add_sub(CSubject* ober)=0;
};

#endif

//通知者员工A

#ifndef __STAFFA_H
#define __STAFFA_H

#include <iostream>
#include <list>
#include "Observer.h"
#include "Subject.h"

class CStaffA:public CObserver
{
public:
CStaffA(std::string name)
{
m_name = name;
}
void add_sub(CSubject* ober)
{
m_sublist.push_back(ober);
}
void notify()
{
for (std::list<CSubject*>::iterator it=m_sublist.begin(); it!=m_sublist.end(); it++)
{
if ((*it)->get_subflag())
{
std::cout<<(*it)->get_subject_status()<<"  "<<m_name.c_str()<<"  赶快努力工作"<<std::endl;
}
}
}
std::string getname()
{
return m_name;
}
private:
std::string m_name;
std::list<CSubject*> m_sublist;
};

#endif
//通知者员工B
#ifndef __STAFFB_H
#define __STAFFB_H

#include <iostream>
#include <list>
#include "Observer.h"
#include "Subject.h"

class CStaffB:public CObserver
{
public:
CStaffB(std::string name)
{
m_name = name;
}
void add_sub(CSubject* ober)
{
m_sublist.push_back(ober);
}
void notify()
{
for (std::list<CSubject*>::iterator it=m_sublist.begin(); it!=m_sublist.end(); it++)
{
if ((*it)->get_subflag())
{
std::cout<<(*it)->get_subject_status()<<"  "<<m_name.c_str()<<"  赶快努力工作"<<std::endl;
}

}
}
std::string getname()
{
return m_name;
}
private:
std::string m_name;
std::list<CSubject*> m_sublist;
};

#endif

//client调用
#include <iostream>
#include "Subject.h"
#include "BigBoss.h"
#include "Boss.h"
#include "StaffA.h"
#include "StaffB.h"

// 这个代码调了好久,在list容器中存放的为指针,那么在使用的时候即为双重指针,我又搞忘了
//这个代码很有意思,值得好好分析
//采用文本编辑的时候,确实容易出现很多低级错误,拼写等
int main(void)
{
CBigBoss* bigboss = new CBigBoss("zhangpg");
CBoss* leader = new CBoss("zhangkuan");
CStaffA* staffa = new CStaffA("xiaoli");
CStaffB* staffb = new CStaffB("Lucy");

staffa->add_sub(bigboss);
staffa->add_sub(leader);

staffb->add_sub(bigboss);
staffb->add_sub(leader);

bigboss->add(leader);
bigboss->add(staffa);
bigboss->add(staffb);

leader->add(staffa);
leader->add(staffb);
leader->add_sub(bigboss);

std::cout<<"this is bigboss action."<<std::endl;
bigboss->action();
std::cout<<"\n\nthis is leader action"<<std::endl;
leader->action();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: