观察者模式:

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

它有四种角色:

主题(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. Converse.js – 开源的 XMPP 聊天客户端

    Converse.js 是一个运行在浏览器的免费和开源的聊天客户端.它可以集成到任何网页.类似于 Facebook 的聊天,它也支持多用户聊天室.Converse.js 可以连接到任何可访问的 XMP ...

  2. Slideout.js – 触摸滑出式 Web App 导航菜单

    Slideout.js 是为您的移动 Web 应用开发的触摸滑出式的导航菜单.它没有依赖,自由搭配简单的标记,支持原生的滚动,您可以轻松地定制它.它支持不同的 CSS3 转换和过渡.最重要的是,它只是 ...

  3. JS Nice – JavaScript 代码美化和格式化工具

    JS Nice 是一款让经过混淆处理的 JavaScript 代码可读更好的工具.它使用一种新型的用于 JavaScript 代码美化的去混淆和去压缩引擎.JSNice 采用先进的机器学习和程序分析技 ...

  4. filezilla sftp 文件和linux 文件不同步的问题

    删除掉以前的链接,重新建立链接就好了

  5. NSFileManager和NSFileHandler的作用

    NSFileManager类可以管理文件系统中的文件和目录,也可以定位.判断是否存在.创建.拷贝.删除文件和目录,还可以获得文件和目录的信息: 对于读写文件,NSFileManager只可以读写字符串 ...

  6. spring.net (1) 概念-控制反转(又名依赖注入)

    Spring.net 作为一个应用程序框架,在构建企业级.net应用程序提供了很多灵活而又丰富的功能(如:依赖注入,aop,数据访问抽象,asp.net 扩展). 控制反转: Inversion of ...

  7. Android Studio no debuggable applications解决方案

    android studio 默认是没有开启debuggable 功能的,在tools里打开该功能即可,Tools->Android->Enable ADB Integration. 刚设 ...

  8. Android自定义控件1--自定义控件介绍

    Android控件基本介绍 Android本身提供了很多控件比如我们常用的有文本控件TextView和EditText:按钮控件Button和ImageButton状态开关按钮ToggleButton ...

  9. IOS 四舍五入 进一法 去尾法

    float numberToRound; int result; numberToRound = 4.51; result = (int)roundf(numberToRound); NSLog(@& ...

  10. RDVTabBarController的基本使用 以及tabbar的防止双点击方法

    RDVTabBarController这个库写得相当不错,所以今天就简单介绍下它的基本使用,看里面可以清楚的知道代码规范的重要性,这个库的使用方法和官方的相识 下载地址:https://github. ...