设计模式之观察者模式

观察者模式

认识观察者模式:
   早些年信息还不是很发达的时候,人们获取信息的途径主要是通过看报纸的形式。今天介绍的观察者模式用报社来作比喻最合适不过了。报社的业务就是出版报纸,顾客向某家报社订阅报纸,只要他们有新报纸出版,就会给你送来。只要你是他们的订阅用户,你就会一直收到新报纸。当你不想看报纸的时候,取消订阅,他们就不会再送新报纸来。只要报社还在运营,就会一直有人(或单位)向他们订阅报纸或取消订阅报纸。
出版者+订阅者 = 观察者模式
观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式通常由四个部分组成:主题接口(对象使用主题接口注册成为观察者,或者把自己从观察者中删除)、具体的主题 对象(一个具体的主题总是实现主题接口,除了注册和撤销方法之外,具体主题还实现了notifyObserver()方法,此方法用于在状态改变时更新所有当前观察者。)、观察者接口(所有潜在的观察者必须实现观察者接口,这个接口只有update()一个方法,当主题状态改变时它被调用。)、具体的观察者对象 (具体的观察者可以实现此接口的任意类。观察者必须注册具体主题,以便接收更新。)
 


当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间松耦合。
上代码:
主题接口
package com.my.observer;

public interface Subject {

    //这两个方法都需要一个观察者作为变量,该观察者是用来注册或被删除的。
    public void  registerObserver(Observer o);
    public void  removeObserver(Observer o);
    //当主题状态改变时,这个方法会被调用,以通知所有的观察者。
    public void notifyObserver();

}
观察者接口
package com.my.observer;

public interface Observer {

    //当气象观测值改变时,主题会把这些状态值当作方法的参数,传递给观察者。
    public void update(float temp,float humidity, float pressure);

}
显示接口
package com.my.observer;

public interface DisplayElement {

    //当布告板需要显示时,调用此方法。
    public void display();
}
具体的主题对象
package com.my.observer;

import java.util.ArrayList;

public class WeatherData implements Subject {

    //增加ArrayList来记录观察者,此ArrayList是在构造器中建立的。
    private ArrayList observers;
    private float temperature;
    private float hmidity;
    private float pressure;

    public WeatherData(){
        observers = new ArrayList();
    }
    public void registerObserver(Observer o){
        //当注册观察者时,我们只要把它加到ArrayList后面即可。
        observers.add(o);
    }
    public void removeObserver(Observer o){
        //当观察者想取消注册,我们把它从ArrayList中删除即可。
        int i = observers.indexOf(o);
        if(i>=0){
            observers.remove(i);
        }
    }
    public void notifyObserver(){
        //把状态告诉每一个观察者,因为观察者已经实现了update方法,所以我们知道如何通知他们。
        for(int i=0;i<observers.size();i++){
            Observer observer = (Observer) observers.get(i);
            observer.update(temperature,hmidity,pressure);
        }
    }
    public void measurementsChanged(){
        //当从气象站获取更新的数据时通知观察者
        notifyObserver();
    }
    public void setMeasurements(float temperature,float hmidity, float pressure){
        //模拟从装置中读取气象站数据
        this.temperature = temperature;
        this.hmidity = hmidity;
        this.pressure = pressure;
        measurementsChanged();

    }

}
具体的观察者对象
package com.my.observer;

public class CurrentConditionsDisplay implements Observer,DisplayElement {

    private float temperature;
    private float humidity;
    private Subject weatherData;

    public CurrentConditionsDisplay(Subject weatherData){
        //构造器需要weatherData对象作为注册用。
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }
    public void update(float temperature,float humidity,float pressure){
        //当update()被调用时,我们把温度和湿度保存起来,然后调用display()。
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }
    public void display(){
        //打印温度和湿度值。
        System.out.println("Current conditions:" + temperature +
        "F degrees and"+ humidity + "%humidity");
    }
}
测试程序
package com.my.observer;

public class WeatherStation {

    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.3f);

    }
}
run:

使用JDK中的支持进行改造:
改造WeatherData使用java.util.Observable
package com.my.observer_inside;

import java.util.Observable;

public class WeatherData extends Observable {

    private float temperature;
    private float hmidity;
    private float pressure;

    public WeatherData(){
        //构造器不再需要为了记住观察者们而建立数据结构了。
    }

    public void measurementsChanged(){
        setChanged();
        notifyObservers();
    }
    public void setMeasurements(float temperature,float hmidity, float pressure){
        //模拟从装置中读取气象站数据
        this.temperature = temperature;
        this.hmidity = hmidity;
        this.pressure = pressure;
        measurementsChanged();

    }

    public float getTemperature(){
        return temperature;
    }
    public float getHmidity(){
        return hmidity;
    }
    public float getPressure(){
        return pressure;
    }
}
重做CurrentConditionsDisplay
package com.my.observer_inside;

import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements Observer,DisplayElement {
    Observable observable;
    private float temperature;
    private float humidity;

    public CurrentConditionsDisplay(Observable observable){
        
        this.observable = observable;
        observable.addObserver(this);
    }
    public void update(Observable obs,Object arg){
        if(obs instanceof WeatherData){
            WeatherData weatherData = (WeatherData) obs;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHmidity();
            display();
        }
    }
    public void display(){
        //打印温度和湿度值。
        System.out.println("Current conditions:" + temperature +
        "F degrees and"+ humidity + "%humidity");
    }
}
run:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值