wb.ouyang

毕竟几人真得鹿,不知终日梦为鱼

导航

head first 设计模式笔记2-观察者模式:气象观测站

设计原则:为了交互对象之间的松耦合设计而努力。

 

1、设计模式的一些理解

  1)知道OO基础,并不足以让你设计出良好的OO系统

  2)良好的OO设计必须具备可复用、可扩充、可维护三个特性

  3)模式可以让我们建造出具有良好OO设计质量的系统

  4)模式被认为是历经验证的OO设计经验

  5)模式不是代码,而是针对设计问题的通用解决方案。你可把它们应用到特定的应用中

  6)模式不是被发明,而是被发现

  7)大多数的模式和原则,都着眼于软件变化的主题

  8)大多数的模式都允许系统局部改变独立于其他部分

  9)我们常把系统中会变化的部分抽出来封装

     10)模式让开发人员之间有共享的语言,能够最大化沟通的价值

 

2、观察者模式:气象观测站

  需求:建立一个下一代Internet气象观测站。该气象站必须建立再我们专利申请中的WeatherData对象上,由WeatherData对象负责追踪目前的天气状况(温度/湿度、气压)。我们希望贵公司能建立一个应用,有三种布告板,分别显示目前的状况、气象统计及简单的预报。当WeatherData对象获得最新的测量数据时,三种布告板必须实时更新。

  而且,这是一个可以扩展的气象站,Weather-O-Rama气象站希望公布一组API,好让其他开发人员可以写出自己的气象布告板,并插入此应用中。我们希望贵公司能提供这样的API。

  气象监测应用的概况:此系统中的三个部分是气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前天气状况给用户看)。WeatherData对象知道如何跟物理气象站联系,以取得更新的数据。WeatherData对象会随即更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。

  我们的工作:建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计和天气预报。

 

 

   认识观察者模式:举例报纸和杂志的订阅

  1)报社的业务就是出版报纸。

  2)向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订户,你就会一直收到新报纸。

  3)当你不想再看报纸的时候,取消订阅,他们就不会再送新报纸来。

  4)只要报社还在运营,就会一直有人向他们订阅报纸或取消订阅报纸。

   出版者 + 订阅者  = 观察者模式,出版者叫做“主题”(Subject), 订阅者叫做"观察者"(Observer)

  

  观察者模式定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

 

  观察者模式,类图设计:

 

   Subject

public interface Subject {
    public void registerObserver(Observer o);
    public void removerObserver(Observer o);
    // 当主题状态改变时,这个方法会被调用,以通知所有的观察者
    public void notifyObservers();
}

  Observer

public interface Observer {
    public void update(float temp, float humidity, float pressure);
}

  DisplayElement

public interface DisplayElement {
    public void display();
}

   WeatherData

public class WeatherData implements Subject {
    private ArrayList observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList();
    }
    
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removerObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0) {
            observers.remove(i);
        }
    }

    @Override
    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();
    }
    
    /**
     * 测试时用这个方法来更新数据
     * @param temperature
     * @param humidity
     * @param pressure
     */
    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;
    }
}

 

   CurrentConditionsDisplay

public class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private Subject weatherData;
    
    public CurrentConditionsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("Current conditions: " + temperature+ "F degrees and "
                + humidity + "% humidity");
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        display();
    }
}

 

   测试代码:

public static void main(String[] args) {
    WeatherData weatherData = new WeatherData();
    CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
    
    // 模拟新的气象测量:一旦气象数据更新就会主动"推送"给每个观察者
    weatherData.setMeasurements(80, 65, 30.4f);
    weatherData.setMeasurements(82, 70, 29.2f);
    weatherData.setMeasurements(78, 90, 30.0f);
    
    // 观察者主动"拉"数据
    System.out.println("观察者主动\"拉\"数据");
    currentConditionsDisplay.update(weatherData.getTemperature(), 
            weatherData.getHumidity(), weatherData.getPressure());
}

 

3、使用jdk提供的观察者相关类 java.util.Observable(主题),java.util.Observer(观察者)

  WeatherData

import java.util.Observable;

/**
 * @author oy
 * @date 2019年8月25日 下午8:44:06
 * @version 1.0.0
 */
public class WeatherData extends Observable {
    private float temperature;
    private float humidity;
    private float pressure;
    
    public WeatherData() {}
        
    public void measurementsChanged() {
        setChanged();
        // 我们没有调用nodifyObservers()传送数据对象,表示我们采用的做法是"拉"
        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;
    }
}

 

  DisplayElement

public interface DisplayElement {
    public void display();
}

 

  CurrentConditionsDisplay

import java.util.Observable;
import java.util.Observer;

/**
 * @author oy
 * @date 2019年8月25日 下午10:34:19
 * @version 1.0.0
 */
public class CurrentConditionsDisplay implements Observer, DisplayElement {
    Observable observable;
    private float temperature;
    private float humidity;
    
    public CurrentConditionsDisplay(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }
    
    @Override
    public void display() {
        System.out.println("Current conditions: " + temperature  + "F degrees and "
                + humidity + "% humidity");
    }

    @Override
    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 static void main(String[] args) {
    WeatherData weatherData = new WeatherData();
    weatherData.setMeasurements(80, 65, 30.4f);
    
    // 创建观察者,并注册
    CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
    // 主动pull数据
    currentDisplay.update(weatherData, null);
    
    // 更新数据,push数据给观察者
    weatherData.setMeasurements(78, 90, 30.0f);
    // 当然,观察者主动pull数据
    //currentDisplay.update(weatherData, null);
}

 

  注意:

 

posted on 2019-08-20 00:00  wenbin_ouyang  阅读(571)  评论(0)    收藏  举报