设计模式----行为型模式之观察者模式(Observer Pattern)

来源:互联网 发布:盘古网络唐山icp备 编辑:程序博客网 时间:2024/05/01 16:14

  下面是阅读《Head First设计模式》的笔记。

观察者模式

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

JDK API内置机制

  JDK1.0版本就已经包含了java.util.Observer和java.util.Observable,TODO。

  java.util.Observer是一个接口,所有使用内置机制实现观察者模式,都需要实现该接口。该接口只定义了一个方法void update(Observable o, Object arg),实现该接口的类(观察者)需要重新该方法,当主题(可观察的)状态改变时,会通知观察者更新实时信息,每一个观察者获取到改变的数据,做出相应的实现(需求不一致),类似于书中介绍的状态布告板、统计布告板和预测布告板等。

  java.util.Observable是一个类,这个类或者继承改类的(继承基类的行为),内置构造和方法如图所示(省事截图):

  

  Observable类中的setChanged()方法提供了更多弹性,当继承该类是,可以调用该方法,根据自己的需求,适当地改变状态,再通知每一个观察者实现通知的功能。

使用观察者模式实现的例子

   

/** * 天气主题(可观察者/目标) * @author mjs * @version 1.0.0 * @filename WeatherData.java * @time 2017-3-9 下午8:26:48 * @copyright(C) 2017 **********有限公司 */package com.shing.design.observerpattern;import java.util.Observable;public class WeatherData extends Observable {    private float temperature; //温度    private float humidity; //湿度    private float pressure; //气压    public float getTemperature() {        return temperature;    }        public WeatherData() {        // TODO Auto-generated constructor stub    }    /**     * 改变状态,通知观察者(布告板)     */    public void measurementsChanged(){        setChanged();        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 void setTemperature(float temperature) {        this.temperature = temperature;    }    public float getHumidity() {        return humidity;    }    public void setHumidity(float humidity) {        this.humidity = humidity;    }    public float getPressure() {        return pressure;    }    public void setPressure(float pressure) {        this.pressure = pressure;    }}
/** * 显示要素 * @author mjs * @version 1.0.0 * @filename DisplayElement.java * @time 2017-3-9 下午8:24:49 * @copyright(C) 2017 **********有限公司 */package com.shing.design.observerpattern;public interface DisplayElement {    /**     * 显示元素方法     */    void display();}
/** * 目前状况布告板 * @author mjs * @version 1.0.0 * @filename CurrentConditionsDisplay.java * @time 2017-3-11 上午9:35:45 * @copyright(C) 2017 **********有限公司 */package com.shing.design.observerpattern;import java.util.Observable;import java.util.Observer;public class CurrentConditionsDisplay implements Observer, DisplayElement {    Observable observable;    private float temperature;    private float humidity;            /**     * 初始化构造,并注册到气象台     * @param observable     */    public CurrentConditionsDisplay(Observable observable) {        super();        this.observable = observable;        observable.addObserver(this);    }    /*      * 布告板显示     */    public void display() {        // TODO Auto-generated method stub        System.out.println("【目前状况布告板】当前状况:" + temperature + "华摄氏度, " + humidity + "%湿度");    }    /*      *      */    public void update(Observable obs, Object arg) {        if(obs instanceof WeatherData){            WeatherData weatherData = (WeatherData) obs;            this.temperature = weatherData.getTemperature();            this.humidity = weatherData.getHumidity();            display();        }    }}
/** * 预测布告板 * @author mjs * @version 1.0.0 * @filename ForecastDisplay.java * @time 2017-3-11 上午9:53:09 * @copyright(C) 2017 **********有限公司 */package com.shing.design.observerpattern;import java.util.Observable;import java.util.Observer;public class ForecastDisplay implements DisplayElement, Observer {    Observable observable;    private float currentPressure = 29.92f;    private float lastPressure;    /**     * 初始化预测布告板,并注册在气象台     * @param observable     */    public ForecastDisplay(Observable observable) {        super();        this.observable = observable;        observable.addObserver(this);    }    /*      * 更新状态     */    public void update(Observable o, Object arg) {        // TODO Auto-generated method stub        if(o instanceof Observable){            WeatherData weatherData = (WeatherData) o;            lastPressure = currentPressure;            currentPressure = weatherData.getPressure();            display();        }    }    /*      *      */    public void display() {        // TODO Auto-generated method stub        System.out.println("【预测布告板】当前气压:" + currentPressure + ",最新气压:" + lastPressure);    }}
/** * 测试类 * @author mjs * @version 1.0.0 * @filename Test.java * @time 2017-3-11 上午10:21:59 * @copyright(C) 2017 **********有限公司 */package com.shing.design.observerpattern;public class Test {    public static void main(String[] args) {        WeatherData weatherDate = new WeatherData();        CurrentConditionsDisplay conditionsDisplay = new CurrentConditionsDisplay(weatherDate);        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherDate);        weatherDate.setMeasurements(57, 87, 110);    }}/**    Console:      【预测布告板】当前气压:110.0,最新气压:29.92    【目前状况布告板】当前状况:57.0华摄氏度, 87.0%湿度*/

推模型和拉模型

  推模型: 主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。

  拉模型:主题对象在通知观察者的时候,只传递少量信息。(上述的例子就是该种模型,如果推模型,请自行脑补哈)。

  注:JDK API中都实现了观察者模式,JavaBeans和Swing,Swing API中JButton类所实现的超类AbstractButton,会看到许多增加与删除倾听者(listener)的方法,这些方法可以让观察者感应到Swing组件的不同类型事件。

结束语

 多学习一点,人生多一分精彩!

  

0 0
原创粉丝点击