观察者模式(二)--《Head First DesignPattern》
我们用Java中自带的观察者模式接口来重写前面的例子。
先看一下类图:

这里用到了一个setChanged函数,它用来标记状态已经改变的事实,好让notifyObservers()知道当它调用时就应该更新观察者。如果调用notifyObservers()之前没有先调用setChanged(),观察者就不会被通知到。setChanged()方法可以让你在更新观察者时,有更大的弹性,你可以适当地通知观察者。
Observable内部是这样的结构:
setChanged(){
changed = true;
}
notifyObservers(Object arg){
if (changed){
for every observer on the list{
call update(this, arg)
}
}
}
notifyObservers(){
notifyObservers(null);
}
注意这里是继承Observable类,而不是接口
package headfirst.observer.weatherobservable; import java.util.Observable;
import java.util.Observer; public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure; public WeatherData() { } public void measurementsChanged() {
//设置changed变量
setChanged();
notifyObservers();
} 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;
}
}
观察者实现Observer接口,
package headfirst.observer.weatherobservable; import java.util.Observable;
import java.util.Observer; public class CurrentConditionsDisplay implements Observer, DisplayElement {
Observable observable;
private float temperature;
private float humidity; public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
} public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
} public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
ForecastDisplay
package headfirst.observer.weatherobservable; import java.util.Observable;
import java.util.Observer; public class ForecastDisplay implements Observer, DisplayElement {
private float currentPressure = 29.92f;
private float lastPressure; public ForecastDisplay(Observable observable) {
observable.addObserver(this);
} public void update(Observable observable, Object arg) {
if (observable instanceof WeatherData) {
WeatherData weatherData = (WeatherData)observable;
lastPressure = currentPressure;
currentPressure = weatherData.getPressure();
display();
}
} public void display() {
System.out.print("Forecast: ");
if (currentPressure > lastPressure) {
System.out.println("Improving weather on the way!");
} else if (currentPressure == lastPressure) {
System.out.println("More of the same");
} else if (currentPressure < lastPressure) {
System.out.println("Watch out for cooler, rainy weather");
}
}
}
package headfirst.observer.weatherobservable; import java.util.Observable;
import java.util.Observer; 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(Observable observable) {
observable.addObserver(this);
} public void update(Observable observable, Object arg) {
if (observable instanceof WeatherData) {
WeatherData weatherData = (WeatherData)observable;
float temp = weatherData.getTemperature();
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);
}
}
main函数
package headfirst.observer.weatherobservable;
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
这里还是要注意几点:
- java.util.Observable是一个“类”而不是一个“接口”,所以我们的类必须继承它,这带来的问题就是Java中只有单继承,所以这限制了Observable的复用能力。而且Observable中的setChanged是被设置为protected的,所以除非你继承自Observable,否则你无法创建Observable实例并把它组合到我们的对象中来。如果实在不行,还是建立我们自己实现一套自己的接口,类似于第一篇所说的。
- Java中的Swing的API就用到了观察者模式。例如我们有一个JButton对象,然后给他设置监听器。这里的监听器就是一个Observer,而JButton就是一个主题。当在JButton上有对应的事件发生的时候,例如点击,那么就会通知监听器,调用类似于update的方法,其实就是ActionListener中的actionPerformed()方法。
观察者模式(二)--《Head First DesignPattern》的更多相关文章
- Java_观察者模式(Observable和Observer)
http://blog.csdn.net/tianjf0514/article/details/7475164/ 一.观察者模式介绍 在Java中通过Observable类和Observer接口实现了 ...
- 设计模式之Protocol实现代理模式
使用场合 使用步骤 不使用protocol实现代理 使用protocol实现代理 一.使用场合 A想让B帮忙,就让B代理 A想通知B发生了一些事情,或者传一些数据给B 观察者模式 二.使用步骤 定义一 ...
- 设计模式(二)The Observer Pattern 观察者模式
问题引入 生成一个公告板显示当时的天气状况,当天气状况发生改变的时候公告板能够实时的更新. 模式定义 定义对象之间的一对多的依赖.当一个对象改变状态时,它的全部依赖者都会自己主动收到通知并自己主动更新 ...
- 委托、事件、Observer观察者模式的使用解析二
一.设计模式-Observer观察者模式 Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新.Observer模式是一种 ...
- 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)
观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...
- Java设计模式(二) 观察者模式
观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新. 1,定义事件源接口 package com.pattern.observer; pub ...
- 观察者模式(一)--《Head First DesignPattern》
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会受到通知并且自动更新. 我们先看下类图: 首先我们自己创建Subject接口,定义了注册观察者,移除观察者和通知 ...
- HeadFirst设计模式 之 C++实现(二):Observer(观察者模式)
观察者模式是最经常使用的设计模式之中的一个,[对象之间多对一的依赖关系,当一个对象发生变化时,其会通知全部依赖它的对象].拿订阅报纸和发行报社打例如,报社採集到news制作新的报纸,派送给订阅的客户. ...
- 设计模式二之观察者模式(Subject-Observer)
观察者模式定义了一系列对象之间的一对多关系,当一个主题对象改变状态,其他所有的依赖者都会收到通知. 好了,你可能会觉得上面的描述略微复杂,较难理解,那么现在我们将用一个简单的例子去讲解这个模式. 我们 ...
随机推荐
- angularJS笔记
1.MVC ng-app: html表头处,每个htnl文件只能有一个ng-app ng-controller :js文件中定义 ng-model:只要引用了angularJS就可以使用 js文件代码 ...
- 为了以后愉快的玩耍,Virtualbox安装Ubuntu
为了以后愉快的玩耍,Virtualbox安装Ubuntu 每次安装虚拟机都是总要折腾一下,毕竟不是特别熟悉,几个小细节总要google半天,为了以后能愉快的玩耍.把这些问题都记录下来,免得再折腾. 此 ...
- Python覆盖率分析工具_Coverage
easy_install安装: easy_install coverage 运行: coverage run test.py coverage report
- openstack 网络
物理节点hosts解析配置
- 【WPF】【火车站点信息查询】
全文涉及到的是C#和XAML 如果这两门语言并非你喜欢的语言,那可以关闭本网页了 本文介绍的是什么? 一个火车站点信息查询软件 本文涉及到的WPF基本知识 Task async await WebCl ...
- 通过一次实验来了解HTML5的 Web Worker
web worker 是运行在后台的 JavaScript,不会影响页面的性能. 当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成. web worker 是运行在后台的 Ja ...
- Sqoop 命令
1)list-databases List available databases on a server sqoop list-databases --connect jdbc:db2:// ...
- Linux查看物理内存信息
Linux查看物理内存信息 1. 查看内存大小 dmidecode|grep Size 输出 Runtime Size: 64 kB ROM Size: 4608 kB Installed Size: ...
- [iOS基础控件 - 6.9.2] 静态单元格 QQ功能列表
使用storyboard设计静态的表格数据 A.实现步骤 1.控制器继承UITableViewController 2.在storyboard中使用TableViewController,删除原来 ...
- HDU 1255 覆盖的面积 (线段树+扫描线+离散化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化 ...