【设计模式】HeadFirst设计模式(二):观察者(Observer)模式
来源:互联网 发布:mysql源码包下载地址 编辑:程序博客网 时间:2024/06/05 17:52
一、观察者模式定义
在观察者模式中,一个被观察者管理所有依赖于它的观察者对象,它定义了一个一对多的依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
主题(被观察者)通过一个共同的接口来更新观察者,观察者依赖于此主题。
二、观察者模式例子——气象监测系统
描述:
气象监测系统分为三个部分:气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)
布告板分为三个:目前状况(显示WeatherData当前观测值)、气象统计(显示最小、平均和最大的观测值)、天气预报(根据气压计显示天气预报)
目标:
当WeatherData对象改变的时候,自动更新三个布告板
实现:
首先,我们看一下WeatherData类的源文件:
getTemperature()、getHumidity()、getPressure()三个方法分别为获得温度、湿度、气压
measurementsChanged():一旦测量更新,此方法会被调用(不需要在乎如何被调用)
然后,我们在measurementsChanged()方法里边添加代码:
<span style="font-family:SimSun;font-size:18px;">public void measurementsChanged() {float temp = getTemperature();float humidity = getHumidity();float pressure = getPressure();//在这个三个方法更新了三个布告板currentConditionsDisplay.update(temp,humidity,pressure);statisticsDisplay.update(temp,humidity,pressure);forecastDisplay.update(temp,humidity,pressure);}</span>我们看到,上边的三个方法像是一个统一的接口,并且是改变的,是针对具体实现编程的,这会导致以后在增加或删除布告板时必须修改程序
在这里,引入一个概念——松耦合:当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
观察者模式提供了一种对象设计,让主题和观察者之间松耦合:
主题只需要知道观察者实现了某个接口(Observer接口),主题不需要知道观察者的具体类是谁,做了什么或其他任何细节
可以画出来类图:
一个主题可以拥有很多的观察者(它们之间是组合的关系,下边会介绍),主题里边有以下方法:
registerObserver():给主题注册观察者
removeObserver():移除主题的观察者
notifyObserver():通知观察者
观察者有一个方法:
update():根据通知进行更新
下边,把气象站的类图设计出来并对其具体实现:
Subject接口:具有注册、移除、通知观察者方法
WeatherData类,继承Subject接口:
(1) 属性:观察者List、温度、湿度、气压
(2) 方法:注册、移除、通知观察者,获得温度、湿度、气压和当状态发生改变的时候通知观察者
Observer接口:具有更新方法
DisplayMent接口:为布告板建立的同意接口,布告板只需要实现display方法
CurrentConditionsDisplay类:根据WeatherData对象显示当前观测值
StatisticsDisplay类:显示最小、平均和最大的观测值
下边用代码进行具体的实现:
Subject接口:
<span style="font-family:SimSun;font-size:18px;">public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();}</span>WeatherData类:
<span style="font-family:SimSun;font-size:18px;">public class WeatherData implements Subject {//放入观察者private ArrayList<Observer> observers;private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<Observer>();}public void registerObserver(Observer o) {observers.add(o);}public void removeObserver(Observer o) {int i = observers.indexOf(o);if (i >= 0) {observers.remove(i);}}public void notifyObservers() {for (int i = 0; i < observers.size(); i++) {Observer observer = (Observer) observers.get(i);observer.update(temperature, humidity, pressure);}}//当状态改变的时候通知观察者public void measurementsChanged() {notifyObservers();}//更新weather data数据public void setMeasurements(float temperature, float humidity,float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}public float getTemperature() {return temperature;}public float getHumidity() {return humidity;}public float getPressure() {return pressure;}}</span>Observer接口:
<span style="font-family:SimSun;font-size:18px;">public interface Observer {void update(float temp,float humidity, float pressure);}</span>DisplayMent接口:
<span style="font-family:SimSun;font-size:18px;">public interface DisplayElement {void display();}</span>CurrentConditionsDisplay类:
<span style="font-family:SimSun;font-size:18px;">public class CurrentConditionsDisplay implements Observer, DisplayElement {private float temperature;private float humidity;//初始化的时候就注册成为观察者public CurrentConditionsDisplay(Subject weatherData) {weatherData.registerObserver(this);}public void update(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;display();}public void display() {System.out.println("Current conditions: " + temperature+ "F degrees and " + humidity + "% humidity");}}</span>StatisticsDisplay类:显示最小、平均和最大的观测值
<span style="font-family:SimSun;font-size:18px;">public class StatisticsDisplay implements Observer, DisplayElement {private float maxTemp = 0.0f;private float minTemp = 200;private float tempSum = 0.0f;private int numReadings;//初始化的时候注册成为观察者public StatisticsDisplay(WeatherData weatherData) {weatherData.registerObserver(this);}public void update(float temp, float humidity, float pressure) {tempSum += temp;numReadings++;if (temp > maxTemp) {maxTemp = temp;}if (temp < minTemp) {minTemp = temp;}display();}public void display() {System.out.println("Avg/Max/Min temperature = "+ (tempSum / numReadings) + "/" + maxTemp + "/" + minTemp);}}</span>下边写一个main函数来验证一下:
<span style="font-family:SimSun;font-size:18px;">public class WeatherStation {public static void main(String[] args) {WeatherData weatherData = new WeatherData();CurrentConditionsDisplay cu = new CurrentConditionsDisplay(weatherData);StatisticsDisplay st = new StatisticsDisplay(weatherData);weatherData.setMeasurements(80, 65, 30.4f);System.out.println("======================");weatherData.setMeasurements(82, 70, 29.2f);System.out.println("======================");weatherData.setMeasurements(78, 90, 29.2f);System.out.println("======================");//下边把StatisticsDisplay这个观察者移除了weatherData.removeObserver(st);weatherData.setMeasurements(90, 70, 35.5f);}}</span>输出:
<span style="font-family:SimSun;font-size:18px;">Current conditions: 80.0F degrees and 65.0% humidityAvg/Max/Min temperature = 80.0/80.0/80.0======================Current conditions: 82.0F degrees and 70.0% humidityAvg/Max/Min temperature = 81.0/82.0/80.0======================Current conditions: 78.0F degrees and 90.0% humidityAvg/Max/Min temperature = 80.0/82.0/78.0======================Current conditions: 90.0F degrees and 70.0% humidity</span>
- 【设计模式】HeadFirst设计模式(二):观察者(Observer)模式
- HeadFirst设计模式 之 C++实现(二):Observer(观察者模式)
- 【HeadFirst设计模式】(二)观察者模式
- Observer 观察者模式 (HeadFirst设计模式 c#)
- HeadFirst设计模式第二章(观察者模式Observer)
- 设计模式(二)Observer - 观察者模式
- HeadFirst 观察者模式(observer)
- 【HeadFirst 设计模式】观察者模式
- HeadFirst 设计模式-观察者模式
- HeadFirst设计模式读书笔记--观察者模式(1)(二)
- HeadFirst设计模式读书笔记--观察者模式(2)(二)
- HeadFirst设计模式读书笔记--观察者模式(3)(二)
- 【白话设计模式二】观察者模式(Observer)
- HeadFirst 设计模式笔记(二)—— observer
- 设计模式--观察者(Observer)
- 设计模式-观察者(Observer)
- 观察者设计模式(Observer)
- Observer(观察者)设计模式
- 数字位数的交换(不能任任意位数)
- hdoj.1788 Chinese remainder theorem again【水题】 2015/04/20
- Android OpenGL ES拾取(使用Java)
- UI UIPageControl
- android studio无法更新(dl-ssl.google.com)
- 【设计模式】HeadFirst设计模式(二):观察者(Observer)模式
- 函数形参为什么要const+引用
- 防御性编程
- POJ 1050 二维动态规划转变成枚举加一维的动态规划!
- 最大黑区域-DFS
- Python中与输入输出相关的三种标准流
- Flex 监测浏览器和主应用程序关闭的相关处理
- Deep learning:三十五(用NN实现数据降维练习)
- POJ2455