观察者模式:

定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并被自动更新。

它有四种角色:

主题(Subject):一个接口,规定了具体主题需要实现的方法。

观察者(Observer):也是一个接口,规定了具体观察者用来更新数据的方法。

具体主题:实现主题接口的一个实例,比如本例中的“就业通知中心”;里面会维护一个具体观察者的集合。本文使用STL中的list。

具体观察者:实现观察者的一个实例,会包含存放主题的引用或者指针。

使用C++实现如下:

包含5个文件,头文件两个:主题类(Subject.h)观察者类(Observer.h)

源文件两个:主题类(Subject.cpp)观察者类(Observer.h)

一个测试文件。

//Subject.h

#ifndef _SUBJECT_H_
#define _SUBJECT_H_
#include "Observer.h"
#include <list>
#include <string>
using namespace std;
class Observer;//注意C++中虽然包含了头文件这里也需要声明
typedef list<Observer*> myList; class Subject{
public:
Subject(){}
virtual ~Subject(){}
virtual void addObserver(Observer* o) = 0;
virtual void deleteObserver(Observer* o) = 0;
virtual void notifyObservers() = 0; }; class SeekJobCenter : public Subject
{
public:
SeekJobCenter();
~SeekJobCenter(){}
void addObserver(Observer* o);
void deleteObserver(Observer* o); void notifyObservers();
void giveNewMessage(string str); private:
string mess;
bool changed;
myList personList; }; #endif

//Subject.cpp

//具体的主题
#include "stdafx.h"
#include "Subject.h"
#include "Observer.h"
#include <list> SeekJobCenter::SeekJobCenter()
{
mess = "";
changed = false;
}
void SeekJobCenter::addObserver(Observer* o)
{
list<Observer*>::iterator it;
//判断原始维护的list中是否存在添加的对象
it = find(personList.begin(), personList.end(), o);
if (it == personList.end())//不存在
{
personList.push_back(o);
}
return;
} void SeekJobCenter::deleteObserver(Observer* o)
{
list<Observer*>::iterator it;
it = find(personList.begin(), personList.end(), o);
if (it != personList.end())//存在
{
personList.remove(*it);
delete(*it);
}
return;
} void SeekJobCenter::notifyObservers()
{
list<Observer*>::iterator it;
if (changed)
{
for (it = personList.begin(); it != personList.end(); ++it)
{
(*it)->hearTelephone(mess);
}
changed = false;
}
return;
} void SeekJobCenter::giveNewMessage(string str)
{
if (0 == strcmp(str.c_str(), mess.c_str()))
{
changed = false;
}
else
{
mess = str;
changed = true;
}
return;
}

//Observer.h

#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include <string>
#include <iostream>
#include <list>
#include "Subject.h"
using namespace std;
class Subject;
/*
观察者基类
*/
class Observer
{
public:
Observer(){};
virtual ~Observer(){};
virtual void hearTelephone(string heardMess) = 0; }; class UniversityStudent : public Observer
{
public:
UniversityStudent(Subject* subject);
virtual ~UniversityStudent(){};
void hearTelephone(string heardMess); private:
Subject* subject; }; class HaiGui : public Observer
{
public:
HaiGui(Subject *subject);
virtual ~HaiGui(){};
void hearTelephone(string heardMess); private:
Subject *subject; }; #endif

//Observer.cpp

 #include "stdafx.h"
#include "Observer.h"
#include "Subject.h" UniversityStudent::UniversityStudent(Subject* subject)
{
if (NULL != subject)
{
this->subject = subject;
}
else
{
return;
} subject->addObserver(this);
}
void UniversityStudent::hearTelephone(string heardMess)
{
std::cout << "I am a university student" << std::endl;
std::cout << "I hear message is " << heardMess << std::endl;
return;
} HaiGui::HaiGui(Subject* subject)
{
if (NULL != subject)
{
this->subject = subject;
}
else
{
return;
}
subject->addObserver(this);
} void HaiGui::hearTelephone(string heardMess)
{
std::cout << "I am a HaiGui" << std::endl;
std::cout << "I hear message is " ;
cout << heardMess << endl;
return;
}

最后一个测试的文件:

#include "stdafx.h"
#include "Observer.h"
#include "Subject.h" int _tmain(int argc, _TCHAR* argv[])
{
SeekJobCenter *center = new SeekJobCenter();
UniversityStudent *chengchaolee = new UniversityStudent(center);
HaiGui *haigui = new HaiGui(center);
center->giveNewMessage("I need a cook");
center->notifyObservers();
center->giveNewMessage("I need a xxxx");
center->notifyObservers(); delete center;
delete chengchaolee;
delete haigui;
return 0;
}

定义两个具体的观察者,并且以具体主题作为参数,代表它观察的对象,然后当主题推送数据时,观察者就会收到消息,即“推数据”的方式,当然还有一种观察者模式采用的是拉数据,即由观察者自己定义需要什么数据,主题在notify的时候并不传递参数而是在观察者更新数据时,将Subject向下转换为具体Subject,从而获取其中相应的数据,这种方式叫做“拉数据”。

值得注意的是,C++在实现的时候,采用list存储具体观察者,需要使用list<Observer*>类型,即使用指针。不然会编译不通过,因为Observer是虚基类,无法实例化。

(一)观察者模式-C++实现的更多相关文章

  1. 23种设计模式--观察者模式-Observer Pattern

    一.观察者模式的介绍      观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...

  2. 谈谈JS的观察者模式(自定义事件)

    呼呼...前不久参加了一个笔试,里面有一到JS编程题,当时看着题目就蒙圈...后来研究了一下,原来就是所谓的观察者模式.就记下来...^_^ 题目 [附加题] 请实现下面的自定义事件 Event 对象 ...

  3. ObserverPattern(观察者模式)

    import java.util.ArrayList; import java.util.List; /** * 观察者模式 * @author TMAC-J * 牵一发而动全身来形容观察者模式在合适 ...

  4. java观察者模式

      像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式.在软件系统中,当一个对象的行为依赖于另一个对象的状态 ...

  5. Backbone源码解析(六):观察者模式应用

    卤煮在大概一年前写过backbone的源码分析,里面讲的是对一些backbone框架的方法的讲解.这几天重新看了几遍backbone的源码,才发现之前对于它的理解不够深入,只关注了它的一些部分的细节和 ...

  6. PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式

    SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分.原文解释是这样的“The Standard PHP Library (SPL) is a col ...

  7. 设计模式--观察者模式初探和java Observable模式

    初步认识观察者模式 观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明: 报社方负责出版报纸. 你订阅了该报社的报纸,那么只要报社发布了新报 ...

  8. 学C#之设计模式系列笔记(2)观察者模式

    一.借鉴说明 1.<Head First Design Patterns>(中文名<深入浅出设计模式>) 2.维基百科,观察者模式,https://zh.wikipedia.o ...

  9. PHP 观察者模式

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. [观察者模式中主要角色] 1.抽象主题(Subject)角色: 抽象主题提供了增加 ...

  10. GJM: 设计模式 - 观察者模式

    GJM : 观察者模式 视频地址: http://www.imooc.com/learn/415 本课程通过一个天气预报的发布和订阅案例,来讲解观察者模式在Java项目中的应用.主要包括观察者模式的结 ...

随机推荐

  1. 前端上传组件Plupload使用指南

    我之前写过一篇文章<文件上传利器SWFUpload使用指南>,里面介绍了上传组件SWFUpload的使用方法,但现在随着html5技术的逐渐推广和普及,再去使用以flash为上传手段的SW ...

  2. go语言 类型:复数类型

  3. Chrome 控制台console的用法

    下面我们来看看console里面具体提供了哪些方法可以供我们平时调试时使用. 目前控制台方法和属性有: ["$$", "$x", "dir" ...

  4. Win10中安装ArcObject帮助

    问题 环境:Win10+VS2010+ArcGIS10.0,未能成功安装其AO帮助文档:使用help library manager手动安装也报错. 选择msha文件: 解决 查看系统事件,发现组件注 ...

  5. iOS开发工具篇-AppStore统计工具 (转载)

    随着iOS开发的流行,针对iOS开发涉及的方方面面,早有一些公司提供了专门的解决方案或工具.这些解决方案或工具包括:用户行为统计工具(友盟,Flurry,Google Analytics等), App ...

  6. XML解析之DOM详解及与SAX解析方法的比较

    XML解析(DOM) XML文件解析方法介绍 我们所用到的NSXMLParser是采用SAX方法解析 SAX(Simple API for XML) 只能读,不能修改,只能顺序访问,适合解析大型XML ...

  7. wifi强度数据采集器(android)

    来源:毕业设计 关键词:wifi数据的采集 SQLite数据库的使用 需求 采集实验室内各坐标处各wifi信号的强度 UI 因为是辅助工具,所以UI写的很简单,如下图 Wifi相关操作 //获取Wif ...

  8. Palo(OLAP database)–MOLAP

    本地安装:D:\Program Files (x86)\Jedox   Palo-Server https://www.openhub.net/p/p4155 维基百科:https://en.wiki ...

  9. VS.net 2013中使用Git建立源代码管理 版本管理

    第一次在VS2013中使用Git,也是第一次使用Git,各种不熟悉.百度各种使用经验,大都不屑于使用VS2013集成的Git,建议下载这个下载那个,我也照学了,确实能实现项目的提交.同步.合并的工作, ...

  10. .net 读写记事本文件

    这是读取文件的代码 StreamReader myreader = File.OpenText(_filepath);//读取记事本文件 string s = ""; s = my ...