观察者模式:定义了对象一对多之间的依赖关系,使得对象发生变化的时候,则所有依赖它的所有对象都会得到通知并且得到更新。
一、在古代的时候,政府发布消息或者要找罪犯的时候,一般都会在城门的位置张贴一张布告,但是认字的老百姓又不多,于是就由念过书秀才读给大家听。
场景已经知道了,那么咱们就通过程序来实现。
首先定义一个通知类和秀才类,通知类用来发布通知,秀才类作为通知类的一个成员变量(采用委托的方式)用来监听发布的通知:
class Scholar;
//通知
class Notice {
public:
Notice();
void setNotice(std::string noticeStr);
void releaseNotice();
private:
std::string _notice;
Scholar* _scholar;
};
//秀才
class Scholar{
public:
Scholar();
~ Scholar();
void getNoticeSay(std::string noticeStr);
};
Notice::Notice() {
_scholar = new Scholar;
}
void Notice::setNotice(std::string noticeStr) {
_notice = noticeStr;
}
void Notice::releaseNotice() {
printf("政府发布公告:%s\n", _notice.c_str());
_scholar->getNoticeSay(_notice);
}
Scholar::Scholar() {
}
Scholar::~Scholar() {
}
void Scholar::getNoticeSay(std::string noticeStr) {
printf("大家注意了,政府发布公告了:%s" , noticeStr.c_str());
}
基本的类已经创建完成了,看看客户端如何调用呢:
int main() {
Notice * notice = new Notice;
//政府政府写好了通知内容
notice->setNotice("今天大家放假一天!");
//发布通知
notice->releaseNotice();
return 0;
}
运行结果:
以上很简单的,政府写好了通知,通知已发布,秀才就知道了,然后念给老百姓听。
二、现在随着社会的进步到了现代社会,人手一只手机,每天就可以通过手机app来看各种各样的新闻,你也看我也看,张三看李四看。只要app新闻一出来,任何关注这个app的手机都会收到新发布的新闻。
这个场景如何搭建呢?
类似于上面的政府发布公告的场景,只不过以前关注政府公告的只有秀才一个人,现在关注app新闻的是很多人。是秀才一个人的时候,作为成员变量就可以,但是现在作为很多人都关注app新闻的时候,应该通过一个列表来维护所有关注者。
既然是面向接口编程,那么首先抽象新闻发布者的基类。
class INews {
public:
INews();
~INews();
//添加观察者
virtual void addReader(IReader* oneReader);
//发布新闻
virtual void releaseNews(std::string newsStr);
};
INews::INews() {
}
INews::~INews() {
}
void INews::addReader(IReader* oneReader) {
}
void INews::releaseNews(std::string newsStr) {
}
基类中有两个方法,一个是添加接受新闻读者的接口,一个是发布新闻的接口。
大家可能觉得怎么没有读者列表?不要担心,读者列表可以放在子类中,也可以放在基类中。
定义一个新闻发布的子类:
//APP新闻发布者
class AppNews : public INews {
public:
void addReader(IReader* oneReader)override;
void releaseNews(std::string newsStr)override;
private:
std::vector<IReader*> _readers;
};
void AppNews::addReader(IReader* oneReader) {
_readers.push_back(oneReader);
}
void AppNews::releaseNews(std::string newsStr) {
printf("发布新闻:%s\n\n", newsStr.c_str());
int cnt = _readers.size();
for(int i = 0; i < cnt; i++) {
_readers.at(i)->update(newsStr);
}
}
新闻发布者中包含了读者对象的列表,那么咱们要把读者对象类的基类定义出来。
class IReader {
public:
IReader(std::string name);
~IReader();
virtual void update(std::string str);
protected:
std::string _name;
};
IReader::IReader(std::string name) {
_name = name;
}
IReader::~IReader() {
}
void IReader::update(std::string str) {
}
定义具体的读者类:
class TrueReader :public IReader {
public:
TrueReader(std::string name);
void update(std::string str)override;
};
TrueReader::TrueReader(std::string name) :IReader(name){
}
void TrueReader::update(std::string str) {
printf("%s看到新闻:%s\n", _name.c_str(), str.c_str());
}
已经定义完成了,看看咱们如何搭建场景了。
int main() {
IReader* zhangsan = new TrueReader("张三");
IReader* lisi = new TrueReader("李四");
IReader* wangwu = new TrueReader("王五");
INews* news = new AppNews();
news->addReader(zhangsan);
news->addReader(lisi);
news->addReader(wangwu);
news->releaseNews("春节放假十五天!");
return 0;
}
运行结果:
新闻app已发布消息,读者就接受到了消息。这就是经典的观察者模式。
新闻是被观察者,读者是观察者,当被观察者发生了变化,就会通知观察者也发生相应的变化。
观察者模式的优点:
1.观察者和被观察者是基类耦合,子类独立;
2.定义了一套观察机制或者是触发机制。