观察者模式是最经常使用的设计模式之中的一个,【对象之间多对一的依赖关系,当一个对象发生变化时,其会通知全部依赖它的对象】。拿订阅报纸和发行报社打例如,报社採集到news制作新的报纸,派送给订阅的客户。以此把最新的消息告知客户。所以。出版社
+ 订阅者 = 观察者模式

这样的一对多的关系,也即“一个”主题、“多个”观察者可以使得观察者只了解主题推送的消息但不知晓当中的细节,而主题握有观察者列表但不干涉到观察者的个人隐私。所以。它们之间相互有交互,但不紧密,不清楚对方的细节。改变主题或者观察者随意一方。并不会影响到对方。

这就是,设计原则之四:为了交互对象之间的松耦合设计而努力。



以下我们来看气象站的建设,满足:有气象数据更新时。通知用户。用户能够在布告板上显示出更新信息。



这个是典型的推送服务(Push),一有新信息就发送给观察者,可是有的时候过于频繁的推送会给用户带来非常多不须要的“垃圾”信息,所以设计主动的询问(Pull)相同非常有意义。

然后是我自己用C++实现的气象站模型,有疏漏的地方请不吝赐教:

<span style="font-size:12px;">// Observer Pattern.h

#include <list>
#include <string> class Observer;
// 实现主题接口
class Subject
{
public:
virtual ~Subject();
virtual registerObserver(Subject *obv);
virtual removeObserver(Subject *obv);
virtual notifyObserver(); // 主题信息改变,由此通知全部观察者"推Push"
protected:
Subject(); // 限制仅仅能子类构造
};
class WeatherData : public Subject
{
private:
list<Observer *> *m_observers;
float m_temperature;
float m_humidity;
float m_pressure;
public:
WeatherData();
virtual ~ WeatherData();
virtual registerObserver(Subject *obv);
virtual removeObserver(Subject *obv);
virtual notifyObserver();
float getTemperature();<span style="white-space:pre"> </span>// 这是让用户自己get想要的信息。主题仅仅须要开放对应的接口就可以
float getHumidity();
float getPressure();
void measureChanged();
};
// 实现观察者接口、显示接口
class Observer
{
public:
Observer();
virtual ~Observer();
virtual void update(float temp, float humidity, float pressure) = 0;
};
class DisplayElement
{
public:
DisplayElement();
virtual ~DisplayElement();
virtual void display() = 0;
};
// 多重继承
class CurrentConditionsDisplay : public Observer, public DisplayElement
{
public:
CurrentConditionsDisplay();
virtual ~CurrentConditionsDisplay();
virtual void update(float temp, float humidity, float pressure);
virtual void display(Subject sub);
private:
Subject *m_sub;
float m_temp;
float m_humidity;
};
class StaticsDisplay : public Observer, public DisplayElement
{
public:
StaticsDisplay();
virtual ~StaticsDisplay();
virtual void update(float temp, float humidity, float pressure);
virtual void display(Subject sub);
private:
Subject *m_sub;
float avg_temp;
float max_temp;
float min_temp;
};
class ForecastDisplay : public Observer, public DisplayElement
{
public:
ForecastDisplay();
virtual ~ForecastDisplay();
virtual void update(float temp, float humidity, float pressure);
virtual void display(Subject sub);
private:
Subject *m_sub;
};</span>



OBSERVER — 想知道咱们公司最新MM情报吗?增加公司的MM情报邮件组即可了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接公布给邮件组,我们作为订阅者(观察者)就能够及时收到情报啦



  观察者模式:观察者模式定义了一种一队多的依赖关系。让多个观察者对象同一时候监听某一个主题对象。

这个主题对象在状态上发生变化时,会通知全部观察者对象,使他们可以自己主动更新自己。

<span style="font-size:12px;">// Observer Pattern(观察者模式)
#include <iostream>
#include "ObserverPattern.h"
using std::cout;
using std::endl; // 主题接口
Subject::~Subject()
{
}
// 气象站的主题接口实现
WeatherData::WeatherData()
{
m_observers = new list<Observer *>;
}
WeatherData::~ WeatherData()
{
}
WeatherData::registerObserver(Subject *obv)
{
if(nullptr != obv)
{
m_observers->push_front(obv);
}
}
WeatherData::removeObserver(Subject *obv)
{
if(nullptr != obv)
{
m_observers->remove(obv);
}
}
WeatherData::notifyObserver()
{
list<Observer *>::iterator iter;
for(; iter!=m_observers->end(); iter++) // 注意呢,迭代器的使用
{
(*iter)->update(m_temperature, m_humidity, m_pressure);
}
}
float WeatherData::getTemperature()
{
return m_temperature;
}
float WeatherData::getHumidity()
{
return m_humidity;
}
float WeatherData::getPressure()
{
return m_pressure;
}
void WeatherData::measureChanged()
{
notifyObserver(); // 主题信息更新,通知全部观察者
}
// 观察者和显示的接口
CurrentConditionsDisplay::CurrentConditionsDisplay(Subject *sub)
{
m_sub = sub;
m_sub->registerObserver(this);
}
CurrentConditionsDisplay::~CurrentConditionsDisplay()
{
m_sub->removeObserver(this);
if(nullptr != m_sub)
delete m_sub;
}
void CurrentConditionsDisplay::update(float temp, float humidity, float pressure)
{
m_temp = temp;
m_humidity = humidity;
display();
}
void CurrentConditionsDisplay::display(Subject sub)
{
cout << "Current condition: "<< m_temp << "F degrees and "
<< m_humidity << "%% humidity" << endl;
}
// 其它两个接口实现的类也是相似的</span>



对于Java中有已经实现的Observable类和Observer,之后将继续学习....  也即MVC中的观察者模式。最大的差别是将主题接口设计成了一个base class,这么做是有缺点的,不适合代码的使用和复用,最好的办法就是设计成接口,多用组合,针对接口编程。但这里仍然放出Java的UML图供学习:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWFsbDAxMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="line-height:26px; font-family:'Microsoft YaHei'">



还有生活中常见的样例:对同一组数据进行统计分析时候。我们希望可以提供多种形式的表示(比如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然须要当数据改变的时候,全部的统计的显示都可以同一时候改变。

重要的是,【会活用设计模式】。

转载请注明出处:http://blog.csdn.net/aall3210_tsingloon/article/details/27712851

HeadFirst设计模式 之 C++实现(二):Observer(观察者模式)的更多相关文章

  1. JAVA设计模式详解(二)----------观察者模式

    有一个模式可以帮助你的对象知悉现况,不会错过该对象感兴趣的事,对象甚至在运行时可以决定是否要继续被通知,如果一个对象状态的改变需要通知很多对这个对象关注的一系列对象,就可以使用观察者模式 .观察者模式 ...

  2. Java设计模式之(十二)——观察者模式

    1.什么是观察者模式? Define a one-to-many dependency between objects so that when one object changes state, a ...

  3. headfirst设计模式(2)—观察者模式

    定义 观察者模式(有时又被称为发布(publish)-订阅(Subscribe)模式,在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察 ...

  4. 委托、事件、Observer观察者模式的使用解析二

    一.设计模式-Observer观察者模式 Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新.Observer模式是一种 ...

  5. Java 设计模式系列(十五)观察者模式(Observer)

    Java 设计模式系列(十五)观察者模式(Observer) Java 设计模式系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Java ...

  6. 设计模式18:Observer 观察者模式(行为型模式)

    Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...

  7. java设计模式解析(1) Observer观察者模式

      设计模式系列文章 java设计模式解析(1) Observer观察者模式 java设计模式解析(2) Proxy代理模式 java设计模式解析(3) Factory工厂模式 java设计模式解析( ...

  8. Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---观察者模式之WeatherReport[转]

      1   2{<HeadFirst设计模式>之观察者模式 }   3{ 主题与观察者                    }   4{ 编译工具 :Delphi7.0          ...

  9. C++设计模式-Observer观察者模式

    Observer观察者模式作用:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己 UML图: S ...

随机推荐

  1. 动态从数据库读取菜单(ASP.NET版)

    这几天一直打算做个从数据读取导航菜单的效果,以前做的时候都是写死的(太死了),好了话不多说,先看效果! 我是个小菜,高手请不要喷!我在网上查了好久,说用menu控件,但是我用了不太好!最后我决定用re ...

  2. pwn学习之dl_resolve学习篇

    一:首先来了解一下linux下常见的攻击缓解机制: CANARY:(金丝雀值,指的是矿工曾利用金丝雀来确认是否有气体泄漏,如果金丝雀因为气体泄漏而中毒死亡,可以给矿工预警),类似于windows GS ...

  3. 第11章 集合、比较和转换(C#入门经典第6版)

    1.集合 数据有一定的限制,最不能忍受的是一旦创建,数组的大小就固定,不能再添加.而集合则包含了数组所具有的功能,且可以任意添加/删减元素项,还有一些其他 功能. 集合的功能主要通过接口来实现,接口包 ...

  4. java中IO递归写入

    package cn.stat.p1.file; import java.io.BufferedWriter; import java.io.File; import java.io.FileWrit ...

  5. [Mugeda HTML5技术教程之10]发布内容

    动画作品制作好后,就要拿来使用,怎么发布到想要的位置也是动画制作者比较关心的问题.这一节,我们讲述怎样将制作好的动画内容发布到想要的地方.对制作好的内容,可能的使用场景主要有以下三种:直接导出:发布到 ...

  6. 网狐6603 cocos2dx 棋牌、捕鱼、休闲类游戏《李逵捕鱼》手机端完整源码分析及分享

    该资源说明: cocos2d 棋牌.捕鱼.休闲类游戏<李逵捕鱼>手机端完整源码,网狐6603配套手机版源码,可以选桌子,适合新手学习参考,小编已亲测试,绝对完整可编译手机端,下载后将文件考 ...

  7. 关于exec命令函数

    exec执行某命令在命令行下没有问题,但是在php中就出错.这个问题99.99%与权限有关,但是exec执行的命令不会返回错误.一个技巧就是使用管道命令,假设你的exec调用如下: exec('con ...

  8. python修改txt文件内容

    ①以r模式打开文件并用readlines方法读入列表l中 ②修改相关行,直接用l[n]形式即可 ③关闭文件 ④以w方式打开文件,用writelines方法写入文件(覆盖文件内容) ⑤关闭文件 需要注意 ...

  9. Net线程池设计

    Net线程池设计 功能描述: 支持创建多个线程池,并统一管理 支持不同线程池的容量控制,以及最少活动线程的设置 支持不同线程池中活动线程的闲时设置,即线程空闲时间到期后即自动被回收 结构设计: Thr ...

  10. Visual Studio下Qt编程中对中文的处理

    Visual Studio下Qt编程中对中文的处理 本文为原创文章,原文地址http://www.cnblogs.com/c4isr/p/qt_develop_in_vs.html Visual St ...