观察者模式(二)--《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)
观察者模式定义了一系列对象之间的一对多关系,当一个主题对象改变状态,其他所有的依赖者都会收到通知. 好了,你可能会觉得上面的描述略微复杂,较难理解,那么现在我们将用一个简单的例子去讲解这个模式. 我们 ...
随机推荐
- openstack 云平台API
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABVYAAAKrCAIAAACV8EEMAAAgAElEQVR4nOydeVgUaZ7n/W9299nd7n
- oracle 字符集转换:AL32UTF8->ZHS16GBK
select userenv('language') from dual; --修改Oracle数据库字符集为ZHS16GBK : SQL>conn / as sysdba; SQL>sh ...
- MySQL索引的创建,查看,删除
在执行CREATE TABLE语句时可以创建索引,也可以单独用CREATE INDEX或ALTER TABLE来为表增加索引. 1.ALTER TABLE ALTER TABLE用来创建普通索引.UN ...
- thymeleaf学习
一.简单表达格式: thymeleaf的官方参考文档 1.变量的表达式:${...} 2.选择变量表达式:*{...} 3.信息表达:#{...} 4.链接URL表达式:@{...} 二.字面值 ...
- linux下查看端口的占用情况
前提:首先你必须知道,端口不是独立存在的,它是依附于进程的.某个进程开启,那么它对应的端口就开启了,进程关闭,则该端口也就关闭了.下次若某个进程再次开启,则相应的端口也再次开启.而不要纯粹的理解为关闭 ...
- Edit Box多行显示时如何使滚动条始终在下方
两种方法: ① CEdit *pEdit = ((CEdit*)GetDlgItem(IDC_EDIT_RXDATA)); pEdit->LineScroll(pEdit->GetLin ...
- UVaLive 6862 Triples (数学+分类讨论)
题意:给定一个n和m,问你x^j + y^j = z^j 的数量有多少个,其中0 <= x <= y <= z <= m, j = 2, 3, 4, ... n. 析:是一个数 ...
- VHDL TestBench基础(转)
TestBench的主要目标是: 实例化DUT-Design Under Test 为DUT产生激励波形 产生参考输出,并将DUT的输出与参考输出进行比较 提供测试通过或失败的指示 TestBench ...
- Spring MVC Framework 实例
一 SpringMVC基础入门,创建一个HelloWorld程序 1 首先,导入SpringMVC需要的jar包. commons-logging-<version>.jar spring ...
- ASP.NET- 使用NPOI导入导出标准Excel
尝试过很多Excel导入导出方法,都不太理想,无意中逛到oschina时,发现了NPOI,无需Office COM组件且不依赖Office,顿时惊为天人,怀着无比激动的心情写下此文. 曾使用过的方法 ...