最近在学习设计模式,用的是 《Head First 设计模式》这本书。感觉这本书写的还是很不错的,深入浅出的介绍了各种常用的设计模式。唯一有点不方便的地方是这本书的例子全都是用的 Java 来实现的。而我主要是用 C++。所以就动手将书上的代码用 C++ 来实现了一遍。

观察者模式

首先是三个接口的代码:

//observer.h
#ifndef OBSERVER_H
#define OBSERVER_H

class Observer
{
public:
    Observer() {}
    virtual void update(double temp, double humidity, double pressure) = 0;
};
#endif // OBSERVER_H
//Subject.h
#ifndef SUBJECT_H
#define SUBJECT_H

#include "observer.h"
#include <QList>
class Subject
{
public:
    Subject();
    void registerObserver(Observer *o);
    void removeObserver(Observer *o);
    void notifyObservers();
private:
    QList<Observer *> m_list;
protected:
    double m_temp;
    double m_humidity;
    double m_pressure;
};

#endif // SUBJECT_H
#include "subject.h"

Subject::Subject()
{

}

void Subject::registerObserver(Observer *o)
{
    m_list.append(o);
}

void Subject::removeObserver(Observer *o)
{
    int i = m_list.indexOf(o);
    if( i >= 0 )
    {
        m_list.removeAt(i);
    }
}

void Subject::notifyObservers()
{
    foreach (Observer * o, m_list)
    {
        o->update(m_temp, m_humidity, m_pressure);
    }
}
#ifndef DISPLAYELEMENT_H
#define DISPLAYELEMENT_H

class DisplayElement
{
public:
    DisplayElement() {}
    virtual void display() = 0;
};

#endif // DISPLAYELEMENT_H

下面是 WeatherData 类:

#ifndef WEATHERDATA_H
#define WEATHERDATA_H

#include "subject.h"

class WeatherData : public Subject
{
public:
    WeatherData();
    void setMeasurements(double t, double h, double p);
    void measurementsChanged();
};

#endif // WEATHERDATA_H
#include "weatherdata.h"

WeatherData::WeatherData()
{

}

void WeatherData::setMeasurements(double t, double h, double p)
{
   m_temp = t;
   m_humidity = h;
   m_pressure = p;
   measurementsChanged();
}

void WeatherData::measurementsChanged()
{
    notifyObservers();
}

最后是四种观察者:

#include "observer.h"
#include "displayelement.h"

class CurrentConditionDisplay : public Observer, public DisplayElement
{
public:
    CurrentConditionDisplay();
    void display() override;
    void update(double temp, double humidity, double pressure) override;
private:
    double m_temp;
    double m_humidity;
    double m_pressure;
};

class ForecastDisplay: public Observer, public DisplayElement
{
public:
    ForecastDisplay();
    void display() override;
    void update(double temp, double humidity, double pressure) override;
private:
    double currentPressure = 29.92f;
    double lastPressure;
};

class HeatIndexDisplay : public Observer, public DisplayElement
{
public:
    HeatIndexDisplay();
    void display() override;
    void update(double temp, double humidity, double pressure) override;
private:
    double m_heatIndex;
    double computeHeatIndex(double t, double rh);
};

class StatisticsDisplay: public Observer, public DisplayElement
{
public:
    StatisticsDisplay();
    void display() override;
    void update(double temp, double humidity, double pressure) override;
private:
    int m_numReadings;
    double m_tempSum;
    double m_maxTemp;
    double m_minTemp;
};
#include "display.h"
#include <iostream>

using std::cout;
using std::endl;

CurrentConditionDisplay::CurrentConditionDisplay()
{

}

void CurrentConditionDisplay::display()
{
    cout << "Current conditions:"  << m_temp
         << " F degrees and " << m_humidity
         << "% humidity" << endl;
}

void CurrentConditionDisplay::update(double temp, double humidity, double pressure)
{
    m_temp = temp;
    m_humidity = humidity;
    m_pressure = pressure;
    display();
}

ForecastDisplay::ForecastDisplay()
{

}

void ForecastDisplay::display()
{
    cout << "Forecast: ";
    if (currentPressure > lastPressure)
    {
        cout << "Improving weather on the way!";
    }
    else if (currentPressure == lastPressure)
    {
        cout << "More of the same";
    }
    else if (currentPressure < lastPressure)
    {
        cout << "Watch out for cooler, rainy weather";
    }
    cout << endl;
}

void ForecastDisplay::update(double temp, double humidity, double pressure)
{
    lastPressure = currentPressure;
    currentPressure = pressure;
    display();
}

HeatIndexDisplay::HeatIndexDisplay()
{

}

void HeatIndexDisplay::display()
{
    cout << "Heat index is " << m_heatIndex << endl;
}

void HeatIndexDisplay::update(double temp, double humidity, double pressure)
{
    (void) pressure;
    m_heatIndex = computeHeatIndex(temp, humidity);
    display();
}

double HeatIndexDisplay::computeHeatIndex(double t, double rh)
{
    double index = (double)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh)
        + (0.00941695 * (t * t)) + (0.00728898 * (rh * rh))
        + (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +
        (0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 *
        (rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) +
        (0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +
        0.000000000843296 * (t * t * rh * rh * rh)) -
        (0.0000000000481975 * (t * t * t * rh * rh * rh)));
    return index;
}

StatisticsDisplay::StatisticsDisplay():
    m_tempSum(0.0),
      m_maxTemp(0),
      m_minTemp(200),
      m_numReadings(0)
{

}

void StatisticsDisplay::display()
{
    cout << "Avg/Max/Min temperature = " << m_tempSum / m_numReadings
         <<  "/" << m_maxTemp << "/" << m_minTemp << endl;
}

void StatisticsDisplay::update(double temp, double humidity, double pressure)
{
    (void) humidity;
    (void) pressure;

    m_tempSum += temp;
    m_numReadings++;

    if (temp > m_maxTemp)
    {
        m_maxTemp = temp;
    }

    if (temp < m_minTemp)
    {
        m_minTemp = temp;
    }

    display();
}

最后是测试代码:

int main(int argc, char *argv[])
{
    WeatherData weatherData;
    CurrentConditionDisplay currentDisplay;
    StatisticsDisplay staticDisplay;
    ForecastDisplay forcastDisplay;
    HeatIndexDisplay heatDisplay;
    weatherData.registerObserver(&currentDisplay);
    weatherData.registerObserver(&staticDisplay);
    weatherData.registerObserver(&heatDisplay);
    weatherData.registerObserver(&forcastDisplay);

    weatherData.setMeasurements(80, 65, 30.4);
    weatherData.setMeasurements(82, 70, 29.2f);
    weatherData.setMeasurements(78, 90, 29.2f);
}

《Head First 设计模式》例子的C++实现(2 观察者模式)的更多相关文章

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

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

  2. php 设计模式 例子

    加载类:include("./Ren.class.php");include "./Ren.class.php"; require("./Ren.cl ...

  3. js设计模式中发布与订阅实现观察者模式例子

    <script> var pubsub = {}; (function(q) { var topics = {}; subuid = -1; q.publish = function(to ...

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

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

  5. Java设计模式(四)——再谈观察者模式

    在本系列的上一篇文章中,我们讨论了JDK对于观察者模式的一套实现.今天我们将要从另一个角度来探索Tomcat中是如何利用观察者模式加载各个组件.不过今天的任务不是解释Tomcat,所以我会单独把重点抽 ...

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

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

  7. [转] JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

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

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

  9. Java设计模式菜鸟系列(两)建模与观察者模式的实现

    转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39755577 观察者(Observer)模式定义:在对象之间定义了一对多的依赖关系,这样一 ...

  10. 设计模式一:关于C++写观察者模式的一些收获

    先贴上部分代码: #include "stdafx.h" #include<iostream> #include<string> #include<v ...

随机推荐

  1. 安卓界面之Toolbar上手

    一.在配置文件采用自定义Style方法去除Actionbar <resources> <style name="MyTheme" parent="The ...

  2. C#使用Aforge调用摄像头拍照

    一. 新建一个Winform项目 二.使用Nuget添加引用 安装下图中红色框住的两个程序包 安装完后发现安装了如下图的程序包,这是因为上述两个程序包存在对其它程序包的依赖. 三.编写程序 1. 窗体 ...

  3. Memcached、Redis、RabbitMQ

    目录 一.Memcached 二.Redis 三.RabbitMQ Memcached Memcache 是一个开源.高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中 ...

  4. Docker容器学习与分享01

    1.什么是容器? 容器技术是一种虚拟化的方案,与传统的虚拟机不同,传统的虚拟机是通过中间层将一台或多台独立的机器虚拟运行于物理硬件之上,而容器是直接运行在操作系统内核之上的用户空间. 所以容器虚拟化又 ...

  5. phoneGap使用 (MAC)

    一.安装 ①先安装NodeJS(如果有的就不用安装了) http://nodejs.org/ ②.sudo npm install -g phonegap 需要等待安装完成 ③.检测是否安装成功 no ...

  6. 简易 Token 验证的实现

    简易 Token 验证的实现 前言 在我们的服务器和客户端的交互中,由于我们的业务中使用 RESTful API 的形式和客户端交互,而 API 又是无状态的,无法帮助我们识别这一次和上一次的请求由谁 ...

  7. CPU指令分类

    指令可以分为三类: 有运算单元参与:compq.subq 无运算单元参与:jge.movq MOV指令可以在CPU内或CPU和存储器之间传送字或字节,它传送的信息可以从寄存器到寄存器,立即数到寄存器, ...

  8. CF1045G:AI robots(CDQ分治)

    Description 火星上有$n$个机器人排成一行,第$i$个机器人的位置为$x_i$,视野为$r_i​$,智商为$q_i​$.我们认为第$i$个机器人可以看到的位置是$[x_i−r_i,x_i+ ...

  9. linked-list-cycle-ii (数学证明)

    题意:略. 这个题最关键的点在于后面,如何找到循环开始的节点. 第一阶段,先用快慢指针找到相遇的节点C.(至于为什么,了解一下欧几里德拓展解决二元不定方程.)A是表头.B是开始循环的位置. 第一次阶段 ...

  10. sql server 压缩备份数据库

    转自 https://www.cnblogs.com/527289276qq/p/6273291.html 今天需要把一个省外项目的数据库从服务器上备份.拷贝到本机(跨地域传输数据库备份文件). 连上 ...