气象监测应用的概念
此系统中的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)
感应装置------气象站ß-(获取数据)--- WeatherData对象---(显示)---显示装置
WeatherData对象跟物理气象站联系,取得更新的数据。WeatherData对象会随即更新三个布告板的显示:目前状况(温度、适度、气压)、气象统计和天气预报。
瞧一瞧刚送到的WeatherData类
WeatherData
getTemperature() //返回温度
getHumidity() //返回湿度
getPressure() //返回气压
measurementsChanged() //一旦气象测量更新,此方法会被调用
我们的工作是实现measurementsChanged(),好让它更新目前状况、气象统计、天气预报的显示布告板。
我们目前知道些什么?
Weather-O-Rama气象站的要求说明并不是很清楚,我们必须搞懂该做些什么。那么我们目前知道些什么呢?
1、WeatherData类具有getter方法,可以取得三个测量值:温度、湿度和气压。
2、当新的测量数据准备好时,measurementsChanged()方法就会被调用(我们不在乎此方法是如何被调用的,我们只在乎它被调用了)。
3、我们需要实现三个使用天气数据的布告板,目前状况布告、气象统计布告、天气预报布告。一旦WeatherData有新的测量,这些布告必须马上更新。
4、此系统必须可扩展,让其他开发人员建立定制的布告用户可以随心所欲的添加或删除任何布告板。
先看一个错误示范
我们一招Weather-O-Rama气象站开发人员的暗示,在measurementsChanged()方法中添加我们的代码:
public class WeatherData{
//实例变量声明
public voidmeasurementsChanged(){
//调用三个getXxx方法,取得最近的测量值,这些方法已经实现了。
floattemp=getTemperature();
floathumidity=gethumidity();
floatpressure=getPressure();
//更新布告板
currentConditionsDisplay.update(temp,humidity,pressure);
statisticsDisplay.update(temp,humidity,pressure);
forecastDisplay.update(temp,humidity,pressure);
}
//这里是其他WeatherData方法
}
我们的实现有什么不对?
currentConditionsDisplay.update(temp,humidity,pressure);
statisticsDisplay.update(temp,humidity,pressure);
forecastDisplay.update(temp,humidity,pressure);
针对具体实现编程,会导致我们以后在增加或删除布告板是必须修改程序。
定义观察者模式:类图
《Interface》
Subject //这是主题接口,对象使用接口
registerObserver()//注册为观察者
removeObserver()//或者把自己从观察者中删除。
notifyObserver()
每个主题可以有许多观察者
《Interface》
Observer
update()//所有观察者必须实现观察者接口,当主题状态改变时它被调用。
这三个布告板都应该有一个也被命名为“subject”的指针来指向WeatherData对象。但是这张图没有画出这样的关系。以免看起来太乱。
public interface Subject{
publicvoid registerObserver(Observer o);
publicvoid removeObserver(Observer o);
publicvoid notifyObserver(Observer o);//当主题状态改变时,这个方法会被调用,以通知所有的观察者。
}
public interface DisplayElement{
public voiddisplay();//当布告板需要显示时,调用此方法。
}
public class WeatherData implementssubject{
privateArrayList observers;//记录观察者,此ArrayList是在构造器中建立的。
privatefloat temperature;
privatefloat humidity;
privatefloat pressure;
publicWeatherData(){
observers=newArrayList();
}
//当注册观察者时,我们只要把它加到ArrayList的后面即可。
publicvoid registerObserver(Observer o){
observers.add(o);
}
//当观察者想取消注册时,我们把它从ArrayList中删除即可。
publicvoid removeObserver(Observer o){
intI = observers.indexOf(o);
if (i>=0 ){
observers.remove(i);
}
}
//把状态告诉每一个观察者。
publicvoid notifyObservers(){
for( int i=0; I < observers.size(); i++){
Observerobserver=(Observer)observers.get(i);
observer.udpate(temperature,humidity, pressure);
}
}
//当从气象站得到更新观测值是,我们通知观察者。
public voidmeasurementsChanged() {
notifyObservers();
}
publicvoid setMeasurements(float temperature, float humidity, float pressure) {
this.temperature= temperature;
this.humidity= humidity;
this.pressure= pressure;
measurementsChange();
}
//WeatherData的其他方法
}
public class CurentConditionDisplayimplements Observer, DisplayElement{
privatefloat temperature;
privatefloat humidity;
privateSubject weatherData;
publicCurentConditionDisplay(Subject weatherData) {
this.weatherData= weatherData;//构造器需要weatherdata对象作为注册之用。
weatherData.registerObserver(this);
}
publicvoid update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity= humidity;
display();//当update被调用时,我们把温度和湿度保存起来,然后调用display
}
publicvoid display() {
system.printLn(“Currentconditions:”+temperature+” and ”+humidity+”% humidity”);
建立一个测试程序
public class WeatherStation{
publicstatic void main(String[] args) {
WeatherDataweatherData = new WeatherData();
CurentConditionDisplaycurentDisplay = new CurentConiditiosDisplay(weatherdata)
StatisticsDispalystatisticsDisplay = new StatisticsDisplay(weatherData);
ForecastDispalyforecastDisplay = new ForecastDisplay(weatherData);
weatherData.setMeasurements(80,65,30.4f);
weatherData.setMeasurements(82,70,29.2f);
weatherData.setMeasurements(78,90,29.2f);
}
}
观察者模式
定义了对象之间的一对多以来,这样一来,当一个对象改变状态时,它的多有依赖者都会收到通知并自动更新。