理解观察者模式

观察者模式是一种行为型模式,适用于对象间一对多的依赖关系,其中一是被观察者,多是观察者,观察者依赖于被观察者。

实例:

以天气的情景做例子:第三方天气软件从气象站获取最新的温度,湿度和气压,当气象站温度,湿度和气压变化时,第三方天气软件要做到及时的更新。在不使用观察者模式时,类图结果是这样的:

 

 

在这个类图结果中,气象站维护了温度,湿度,气压数据,同时还要介入第三方软件获取天气数据的接口或者类,当天气数据变化时,对第三方软件一一进行通知。
这个结构的一个明显缺陷是:每接入一个第三方软件,气象站需要做相应的更改,扩展性太差。

观察者模式实现

观察者模式,则是将被观察者看做主题(Subject)类(本例的主题是WeatherStation),第三方天气软件抽象为Observer接口,类图结构如下:

 

 

这种结构的设计,使得第三方接入变得简单,当有新的第三方软件需要获取天气数据的时候,仅需要实现observer接口,然后注册到主题类中即可,无论接入多少个第三方软件,气象站类不需要做任何的改动。

代码实现:

public class WeatherStation {
    List<Observer> observerList;
    private float temperature;//气温
    private float pressure;//气压
    private float humidity;//湿度
    public WeatherStation() {
        observerList = new ArrayList<Observer>();
    }
    public void setData(float temerature, float pressure, float humidity) {
        this.humidity = humidity;
        this.pressure = pressure;
        this.temperature = temerature;
        noticeThirdParty();//通知第三方
    }

    private void noticeThirdParty() {
        if (observerList != null && observerList.size() > 0) {
            for (Observer observer : observerList) {
                observer.update(this.temperature, this.pressure, this.humidity);
            }
        }
    }
    public void registerObserver(Observer observer) {
        observerList.add(observer);
    }
    public void removeObserver(Observer observer) {
        observerList.remove(observer);
    }
}
public interface Observer {
    public void update(float temperature,float pressure,float humidity);
}
public class XiaomiWeather implements Observer {

    private float temperature;//气温
    private float pressure;//气压
    private float humidity;//湿度
    public XiaomiWeather() {
    }
    @Override
    public void update(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }
    public void display() {
        System.out.println("xiaomi当前温度:" + temperature);
        System.out.println("xiaomi当前湿度:" + humidity);
        System.out.println("xiaomi当前气压:" + pressure);

    }
}
public class MojiWeather implements  Observer {
    private float temperature;//气温
    private float pressure;//气压
    private float humidity;//湿度

    public MojiWeather(){
    }
    @Override
    public void update(float temperature, float pressure, float humidity) {
        this.temperature=temperature;
        this.pressure=pressure;
        this.humidity=humidity;
        display();
    }
    public void display(){
        System.out.println("moji当前温度:"+temperature);
        System.out.println("moji当前湿度:"+humidity);
        System.out.println("moji当前气压:"+pressure);
    }
}
public class Test {
    public static void main(String[] args) {
        WeatherStation subject =new WeatherStation();
        subject.setData(12,100,20);
        MojiWeather mojiWeather = new MojiWeather();
        subject.registerObserver(mojiWeather);
        XiaomiWeather xiaomiWeather =new XiaomiWeather();
        subject.registerObserver(xiaomiWeather);
        subject.setData(11,200,44);
    }
}

使用java内置的观察者

Observable:类而不是接口(被观察者)
Observer:观察者,是个接口
因此,我们继承java内置的观察者,对代码进行改造

//定义个天气对象
public class WeatherData {
    private float temperature;//气温
    private float pressure;//气压
    private float humidity;//湿度
    public WeatherData(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.humidity=humidity;
        this.pressure=pressure;
    }
    public float getTemperature() {
        return temperature;
    }
    public void setTemperature(float temperature) {
        this.temperature = temperature;
    }
    public float getPressure() {
        return pressure;
    }

    public void setPressure(float pressure) {
        this.pressure = pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    public void setHumidity(float humidity) {
        this.humidity = humidity;
    }
}
//改造被观察者
public class WeatherStation extends Observable {

    private WeatherData weatherData;

    public WeatherStation( ) {
        super();
    }
    public void setData(WeatherData weatherData ){
        this.weatherData = weatherData;
        this.setChanged();  //标识数据变化,否则不会通知
        super.notifyObservers(weatherData);
    }
}
public class MojiWeather implements Observer {
    private WeatherData weatherData;
    @Override
    public void update(Observable o, Object arg) {
       if(arg instanceof  WeatherData){
            this.weatherData =(WeatherData) arg;
            display();
       }
    }
    public void display(){
        System.out.println("moji当前温度:"+this.weatherData.getTemperature());
        System.out.println("moji当前湿度:"+this.weatherData.getHumidity());
        System.out.println("moji当前气压:"+this.weatherData.getPressure());
    }
}
//改造观察者
public class XiaomiWeather  implements Observer {
    private WeatherData weatherData;
    @Override
    public void update(Observable o, Object arg) {
        if(arg instanceof  WeatherData){
            this.weatherData =(WeatherData) arg;
            display();
        }
    }
    public void display(){
        System.out.println("xiaomi当前温度:"+this.weatherData.getTemperature());
        System.out.println("xiaomi当前湿度:"+this.weatherData.getHumidity());
        System.out.println("xiaomi当前气压:"+this.weatherData.getPressure());
    }
}
//测试
public class Test {
    public static void main(String[] args) {
        WeatherData weatherData =new WeatherData(10,20,100);
        WeatherStation subject= new WeatherStation();
        MojiWeather mojiWeather = new MojiWeather();
        XiaomiWeather xiaomiWeather = new XiaomiWeather();
        subject.addObserver(mojiWeather);
        subject.addObserver(xiaomiWeather);
        subject.setData(weatherData);
    }
}

观察者模式注意点:

1)观察者模式应避免循环引用
2)观察者模式中顺序通知容易造成通知卡死,因为一个通知失败会造成后续通知不执行,可以采用异步通知的方式
3)通知有两种方式,一种是将变化的数据通知给观察者,一种是通知观察者数据已变化,观察者主动去拉取最新的数据。java内置的Observable也提供了这两种方法

 

 

4)继承了java的Observable对象后,数据变化时,需要主动调用setChanged()方法, 否则不会通知



链接:https://www.jianshu.com/p/a16452a35629

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值