设计模式:观察者模式

设计模式可能是一个高深的问题,目测逼格极高,驾驭起来也肯定是有难度的,为了理解一篇文章中的一些概念,我也第一次鼓起勇气直面了这个问题,虽然是初出茅庐的小菜鸟,但也是有一番收获的,这篇文章粗浅的认识了观察者模式,将会以一个气象站的例子加以描述.

观察者模式

简要的描述

观察者模式,还有一个别名,叫做发布-订阅模式,相比于观察者模式这个名称来说,后者更具有表现力,观察者模式有两个主角,一个叫做Observer, 另一个叫做Subject.
下面给出一些比较官方的东西,观察者模式的组成

  1. 抽象目标角色 (Subject): 目标角色知道它的观察者,可以有任意多个观察者观察同一个目标。并且提供注册和删除观察者对象的接口。目标角色往往由抽象类或者接口来实现。
  2. 抽象观察者角色(Observer): 为那些在目标发生改变时需要获得通知的对象定义一个更新接口。抽象观察者角色主要由抽象类或者接口来实现。
  3. 具体目标角色(Concrete Subject): 将有关状态存入各个Concrete Observer对象。当它的状态发生改变时, 向它的各个观察者发出通知。
  4. 具体观察者角色(Concrete Observer): 存储有关状态,这些状态应与目标的状态保持一致。实现Observer的更新接口以使自身状态与目标的状态保持一致。在本角色内也可以维护一个指向Concrete Subject对象的引用。

不过概念总是抽象的, 死板的定义往往不能给出直观的感受, 在详细的解说之前, 我们还需要了解观察者模式到底要实现什么目的, 这样我们也可以进行有目的的学习.

For What ?

观察者模式往往会被用于满足这样的需求: 一个对象的状态发生变化, 其他对象也要随之作出变化.

观察者模式应该允许一个Concrete Subject有若干个Concrete Observer对其进行观察, 当Concrete Subject的状态发生改变时, 该模式可以通知所有该Concrete Subject的Concrete Observer,并且这些观察者会作出相应的改变, 而不是Concrete Subject的观察者对象不应该受到任何通知.

假设一个气象站管理了3个布告板和一个气象中心, 该模式可以实现在气象中心有新的气象信息时,3个布告板都能受到通知,并且可以以自己的方式展示这些信息.

该模式致力于降低对象之间的耦合性.

详细讲解

使用气象站例子
语言: c++

/*
*设计模式之观察者模式实验代码
*/
#include <iostream>
#include <vector>
using namespace std;
//Observer 抽象类 抽象目标角色(或称主题)
class Observer{
public:
    ///update方法 收到通知时会执行这个方法
    virtual void update(float temp, float humidity, float pressure) = 0;
};
//Subject 抽象类
class Subject{
public:
    virtual void registerObserver(Observer* o) = 0; //注册自己的观察者
    virtual void removeObserver(Observer* o) = 0;   //将自己从该观察者中移除
    virtual void notifyObserver() = 0;              //通知所有观察者
};
//展示抽象类
class Display{
public:
    //将数据传递给外部
    virtual void display() = 0;

};


//订阅的目标数据 天气情况 属于——具体目标角色(Concrete Subject)
//继承于Subject 
class WeatherData : public Subject{
private:
    std::vector<Observer*> observerVector;
    float temperature;
    float humidity;
    float pressure;
public:
    WeatherData(){
        //构造函数
    }
    ~WeatherData(){

    }
    virtual void registerObserver(Observer *o){
        observerVector.push_back(o);
    }
    virtual void removeObserver(Observer *o){
        std::vector<Observer*>::iterator it;
        for(it = observerVector.begin(); it != observerVector.end(); ++it){

            if((*it) == o){
                observerVector.erase(it);
                break;
            }
        }
    }
    //实现通知观察者接口 遍历所有观察者 执行update 观察者获取到数据
    virtual void notifyObserver(){
        std::vector<Observer*>::iterator it;
        for(it = observerVector.begin(); it != observerVector.end(); ++it){
            (*it)->update(temperature, humidity, pressure);
        }
    }
    //当从气象站获得新的数值时 通知观察者
    void MeasurementsChanged(){
            notifyObserver();
    }
    // 获取数据
    void SetMeasurements(float temperature, float humidity, float pressure){
            this->temperature = temperature;
            this->humidity = humidity;
            this->pressure = pressure;
            MeasurementsChanged();
    }

};

class WeatherObserver: public Display,public Observer {
private:
    float temperature;
    float humidity;
    Subject* weatherData;
public:
    WeatherObserver(){

    }
    ~WeatherObserver(){

    }
    //接受具体Subjet的注册
    void CurrentConditionsDisplay(Subject* weatherData){
        this->weatherData = weatherData;
        weatherData->registerObserver(this);
    }
    virtual void display(){

        cout << "Current coditions: " << temperature << "F degress and " << humidity << "%% humidity" << endl;
    }
    virtual void update(float temp, float humidity, float pressure){
        this->temperature = temp;
        this->humidity = humidity;
        display();

    }

};
int main(){
    WeatherObserver wo;
    WeatherData * pwd = new WeatherData();
    wo.CurrentConditionsDisplay(pwd);
    //更新气象数据
    pwd->SetMeasurements(20,30,10); //一旦更新数据 它的观察者立刻做出反应执行display()
    return 0;
}

参考

博文: http://blog.csdn.net/harry_j/article/details/8435197
百度百科
其他相关博文

posted @ 2016-09-16 16:54 Smalldy 阅读(...) 评论(...) 编辑 收藏