Head First 之 Design Pattern(二):Observer Pattern

观察者模式是最常用的设计模式之一,【对象之间多对一的依赖关系,当一个对象发生变化时,其会通知所有依赖它的对象】。拿订阅报纸和发行报社打比方,报社采集到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图供学习:

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

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

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

Head First 之 Design Pattern(二):Observer Pattern,布布扣,bubuko.com

时间: 2024-10-07 06:30:08

Head First 之 Design Pattern(二):Observer Pattern的相关文章

Learning JavaScript Design Patterns The Observer Pattern

The Observer Pattern The Observer is a design pattern where an object (known as a subject) maintains a list of objects depending on it (observers), automatically notifying them of any changes to state. When a subject needs to notify observers about s

设计模式(二)The Observer Pattern 观察者模式

问题引入 生成一个公告板显示当时的天气状况,当天气状况发生改变的时候公告板能够实时的更新. 模式定义 定义对象之间的一对多的依赖.当一个对象改变状态时,它的全部依赖者都会自己主动收到通知并自己主动更新. 认识模式 该模式在生活中是非经常见的.想想生活中的各种各样的检測系统,报警系统,一旦有重要事件发生时,有关系统总能及时的收到通知.这就是观察者模式. 问题解决 关于观察者模式,java实际上给了我们内置的支持(能够看出该模式还是非经常常使用的吧!)可是我们经常会自己实现. 为什么呢?我们后面会给

[Design Pattern] Observer Pattern 简单案例

Observer Pattern,即观察者模式,当存在一对多关系,例如一个对象一有变动,就要自动通知被依赖的全部对象得场景,属于行为类的设计模式. 下面是一个观察者模式的简单案例. Observer 定义观察者的接口,定义需要观察的对象,已经被通知的接口.BinaryObserver, OctalObserver, HexaObserver 各自实现了 Observer 接口. Subject 是被观察的对象,记录了观察该对象的观察者列表,自身有变动,即可通知观察者列表中的各个观察者. 代码实现

Design Pattern: Observer Pattern

1. Brief 一直对Observer Pattern和Pub/Sub Pattern有所混淆,下面打算通过这两篇Blog来梳理这两种模式.若有纰漏请大家指正. 2. Use Case 首先我们来面对一个老到跌渣的故事,并以从未听说过Observer Pattern为前提. 假设要设计一个新闻订阅系统,新闻分为商业.体育和八卦3种,而查收终端有PC.移动终端等,后续还不断增加新闻种类和查收终端. 需求如上,下面我们根据OOD的方式来构建概念模型. 新闻 <- 分类新闻 终端 <- 分类终端

设计模式之二:观察者模式(Observer Pattern)

先看下观察者模式的定义: The Observer Pattern defines a one-to-many denpendency between objects so that when one object changes state, all of its dependents are notified and updated automatically.:观察者模式定义了对象间一对多依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新. 观察者模式又叫发布-

设计模式之Observer Pattern

Declaration 首先声明, 本篇blog的内容是参考Design pattern FAQ Part 2 (Design pattern training series)这篇博文写的, 图片也是来自这篇博客. 部分是翻译, 加上自己的理解形成这篇博文. 希望和大家一起学习设计模式, 共同进步. Scene for Observer Pattern 举个例子说明在什么情况下会使用观察者模式,比如说一个网站,有订阅的功能,读者在提交订阅申请的时候会写入自己的邮件地址.那么每当这个网站有新内容更

C#设计模式(17)——观察者模式(Observer Pattern)

原文:C#设计模式(17)--观察者模式(Observer Pattern) 一.引言 在现实生活中,处处可见观察者模式,例如,微信中的订阅号,订阅博客和QQ微博中关注好友,这些都属于观察者模式的应用.在这一章将分享我对观察者模式的理解,废话不多说了,直接进入今天的主题. 二. 观察者模式的介绍 2.1 观察者模式的定义 从生活中的例子可以看出,只要对订阅号进行关注的客户端,如果订阅号有什么更新,就会直接推送给订阅了的用户.从中,我们就可以得出观察者模式的定义. 观察者模式定义了一种一对多的依赖

C#设计模式之十六观察者模式(Observer Pattern)【行为型】

原文:C#设计模式之十六观察者模式(Observer Pattern)[行为型] 一.引言 今天是2017年11月份的最后一天,也就是2017年11月30日,利用今天再写一个模式,争取下个月(也就是12月份)把所有的模式写完,2018年,新的一年写一些新的东西.今天我们开始讲"行为型"设计模式的第四个模式,该模式是[观察者模式],英文名称是:Observer Pattern.还是老套路,先从名字上来看看."观察者模式"我第一次看到这个名称,我的理解是,既然有&quo

Learning JavaScript Design Patterns The Singleton Pattern

The Singleton Pattern The Singleton pattern is thus known because it restricts instantiation of a class to a single object. Classically, the Singleton pattern can be implemented by creating a class with a method that creates a new instance of the cla