设计模式:观察者模式

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

观察者模式

简要的描述

观察者模式,还有一个别名,叫做发布-订阅模式,相比于观察者模式这个名称来说,后者更具有表现力,观察者模式有两个主角,一个叫做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  阅读(623)  评论(2编辑  收藏  举报