zoukankan      html  css  js  c++  java
  • 设计模式:观察者模式

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

    观察者模式

    简要的描述

    观察者模式,还有一个别名,叫做发布-订阅模式,相比于观察者模式这个名称来说,后者更具有表现力,观察者模式有两个主角,一个叫做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
    百度百科
    其他相关博文

  • 相关阅读:
    学习!
    第10天:自适应高度
    第9天:第一个CSS布局实例
    nodejs in windows
    网络驱动器无法显示SVN图标问题
    nodejs获取文件修改时间
    gears旅程
    @import和link标签的差别
    evernote诡异bug
    让你的chromium支持支付宝
  • 原文地址:https://www.cnblogs.com/xdblog/p/5876712.html
Copyright © 2011-2022 走看看