设计模式之观察者模式

来源:互联网 发布:物理补课软件 编辑:程序博客网 时间:2024/06/05 15:08

观察者模式

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

举例

  现在有一个气象站,需要发布发布天气,气象站只提供数据,需要编写程序将天气发布给每一个用户,用户接收也可能有多种模式,有的是当前天气状况也有的是天气预报。

  这时候就可以使用观察者模式,进行一对多推送,观察者模式主要就是订阅、发布过程,用户订阅了天气信息,气象站对用户及时发布最新的天气信息,用户也可以随时取消订阅。

observer

  如图

  • Subject接口: 主题接口,也就是被观察对象的接口
  • Observer接口: 观察者接口
  • DisplayElement接口: 展示接口
  • WeatherData: 具体的被观察对象
  • CurrentConditionDisplay: 当前天气状态的展示

  通过上图,就可以看出观察者模式的运行情况了,具体主题实现Subject接口,具体展示实现Observer和DisplayElement接口,Subject中有注册、移除、通知三个方法,这样就可以对观察者进行注册移除,并通知观察者。

// 模拟天气站,发布天气public class WeatherStation{    public static void main(String[] args)    {        WeatherData weatherData = new WeatherData();        CurrentConditionDisplay current = new CurrentConditionDisplay(weatherData);        weatherData.setMeasurement(35, 65, 30.4f);        weatherData.setMeasurement(36, 67, 30.5f);        weatherData.setMeasurement(34, 66, 30.5f);        // 移除观察者        current.remove();        weatherData.setMeasurement(33, 62, 30.5f);    }}

输出结果

当前状态: 温度 35.0度 湿度 65.0%
当前状态: 温度 36.0度 湿度 67.0%
当前状态: 温度 34.0度 湿度 66.0%

  这样就基本完成了气象站的需求,可以对观察者们发布最新的天气信息。

Java Jdk中内置的观察者模式实现

  • Observable类: 对应上述的Subject,也就是被观察的对象要实现的接口
  • Observer接口: 对应上述的Observer接口,观察者实现的接口

  使用内置的对象来实现观察者模式整体上跟上述基本相同,但是Observable是一个类,是需要用继承方式来扩展。

  在Observable中,有一个setChanged()方法,在通知之前,需要调用这个方法,来表明状态已经改变了。

  在Observer中的update()方法有两个参数,一个是一个Observable对象,还有一个就是Observable对象“推”的一个对象。在jdk内置方法中,发布有两种形式,一种是”推”,一种是”拉”,在Observable类中的notifyObservers()方法里,可以带一个参数,代表是”推”,推送给每一个观察者,也可以不带参数,就默认是”拉”方式,这样就变得更为灵活。

  但是Observable是一个类,而不是一个接口,这样在程序扩展性上也有了一些限制,如果可以满足需求,就可以直接使用,如果不行,那么只能自己写一套观察者模式出来,就像最前面那样。

使用jdk中观察者的类

import java.util.Observable;// 使用jdk提供的内置对象完成观察者模式public class WeatherData extends Observable{    private float temperature;    private float humidity;    private float pressure;    public WeatherData(){}    public void measurementsChanged()    {        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;    }}
import ObserverPattern.DisplayElement;import java.util.Observable;import java.util.Observer;// 展示当前状态public class CurrentConditionDisplay implements Observer, DisplayElement{    Observable observable;    private float temperature;    private float humidity;    public CurrentConditionDisplay(Observable observable)    {        this.observable = observable;        observable.addObserver(this);    }    public void remove()    {        observable.deleteObserver(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("当前状态: 温度 " + temperature + "度 " + " 湿度 " + humidity + "%");    }}

  以上具体代码都可以在我的github中查看
  地址:https://github.com/yangliu0/DesignPatterns

0 0