观察者模式(二)--《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)
观察者模式定义了一系列对象之间的一对多关系,当一个主题对象改变状态,其他所有的依赖者都会收到通知. 好了,你可能会觉得上面的描述略微复杂,较难理解,那么现在我们将用一个简单的例子去讲解这个模式. 我们 ...
随机推荐
- [HIve - LanguageManual] Join Optimization (不懂)
Join Optimization Join Optimization Improvements to the Hive Optimizer Star Join Optimization Star S ...
- Spring学习笔记(一) Spring基础IOC、AOP
1. 注入类型 a) Spring_0300_IOC_Injection_Type b) setter(重要) c) 构造方法(可以忘记) d) ...
- Apache Rewrite常用设置说明
例子: RewriteEngine on 打开引擎 RewriteRule test.html /test.php [L] RewriteRule test.html?$ /tianqi.php?s1 ...
- pyinstaller使用小结
安装pyinstaller pip install -U pyinstaller 生成控制台程序 pyinstaller ./example.py 在当前目录的dist文件夹内可以找到编译成功的程序 ...
- Java8新特性 1——利用流和Lambda表达式操作集合
Java8中可以用简洁的代码来操作集合,比如List,Map,他们的实现ArrayList.以此来实现Java8的充分利用CPU的目标. 流和Lambda表达式都是Java8中的新特性.流可以实现对集 ...
- Spark的应用程序
Spark的应用程序,分为两部分:Spark driver 和 Spark executor.
- 现代程序设计homework——04
题目: 详见:http://www.cnblogs.com/xinz/p/3341551.html 题目本身确实很难,“很难想到一个比较优雅的算法”,这是一个老师请来专门讲解这道题的大牛的原话.确实, ...
- JSF 2 dropdown box example
In JSF, <h:selectOneMenu /> tag is used to render a dropdown box – HTML select element with &q ...
- AngularJS 学习笔记二
AngularJS指令 指令 描述 讲解 ng_app 定义应用程序的根元素. 指令 ng_bind 绑定 HTML 元素到应用程序数据. 简介 ng_click 定义元素被单击时的行为. HTML ...
- 48种CIFilter
48种CIFilter CIAdditionCompositing //影像合成 CIAffineTransform //仿射变换 CICheckerboardGe ...