0
点赞
收藏
分享

微信扫一扫

设计模式:观察者模式

zhongjh 2022-04-14 阅读 48
java

观察者模式是在数据发生变化的时候,能及时捕捉变化并进行相关操作,适用场景有监测天气变化

interface Subject {
    public void registerObserver(Observer o);    //数据源提供用于(观察者想要获取数据源时调用此方法注册)

    public void removeObserver(Observer o);        //数据源提供用于(观察者不再需要数据源数据时,退出注册)

    public void notifyObservers();                //数据源向注册在案的所有观察者发送数据
}

interface DisplayElement {
    public void display();        //观察者调用此方法向用户显示数据
}

interface Observer {
    public void update(double temp, double humidity, double pressure);
    //观察者当接收到来自数据源的信息时,调用此方法更新自身数据
}

/**
 * 天气数据
 */
class WeatherData implements Subject {
    private ArrayList observers;
    private double temperature; //温度
    private double humidity;    //湿度
    private double pressure;    //气压

    /*当数据源初始化时,维护一个记录观察者的列表*/
    public WeatherData() {
        observers = new ArrayList();
    }

    /*实现Subject接口的注册方法*/
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    /*实现Subject接口的取消注册方法*/
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0) observers.remove(i);
    }

    /*实现Subject接口的notifyObservers(),用于向所有注册的观察者发送数据*/
    public void notifyObservers() {
        for (int i = 0; i < observers.size(); i++) {
            Observer observer = (Observer) observers.get(i);
            observer.update(temperature, humidity, pressure);
            //更新数据,该操作会调用ConditionDisplay类的update方法
        }
    }

    /*当有新数据时,向注册的观察者发送数据*/
    public void measurementsChanged() {
        notifyObservers();
    }

    /*向获取数据的设备提供接口
    当气象观察站获得新数据
    会调用此接口向WeatherData写数据
    以便WeatherData向观察者发送数据*/
    public void setMeasurements(double temp, double humditidy, double pressure) {
        this.temperature = temp;
        this.humidity = humditidy;
        this.pressure = pressure;
        measurementsChanged();        //表示有了新数据
    }
}

class ConditionDisplay implements Observer,DisplayElement{
    private double temperature;
    private double humidity;
    private double pressure;
    private String name;
    private Subject weatherdata;	//观察者也要维护一个中介(WeatherData)作为数据源

    //当观察者初始化时,需要指定数据源和观察者的名字
    public ConditionDisplay(Subject weatherdata,String name) {
        this.name = name;
        this.weatherdata = weatherdata;//接收天气数据
        weatherdata.registerObserver(this);//注册当前观察者实例
        //向数据源注册,代表需要从数据源获取数据
    }

    //把数据打印给用户
    public void display() {
        System.out.println("Observer "+name+" data:");
        System.out.println("temperature: "+temperature);
        System.out.println("humidity: "+humidity);
        System.out.println("pressure: "+pressure);
        System.out.println();
    }

    /*当从数据源(WeatherData)获得数据后,用新数据更新自身数据*/
    public void update(double temp, double humidity, double pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        display();//信息更新完后,自动打印
    }
}

class WeatherStation {

    public static void main(String[] args) {
        WeatherData weatherdata = new WeatherData();
        ConditionDisplay cd1 = new ConditionDisplay(weatherdata, "ob1");
//        ConditionDisplay cd2 = new ConditionDisplay(weatherdata, "ob2");
//        ConditionDisplay cd3 = new ConditionDisplay(weatherdata, "ob3");

        /*数据源获得数据,并调用WeatherData的方法,来向WeatherData 写数据*/
        weatherdata.setMeasurements(10.5, 10.4, 10.8);
        weatherdata.setMeasurements(10.4, 10.1, 10.2);
    }
}

下面是Java已经写好的观察者类

//Java自定义类

interface DisplayElement {
    public void display();        //观察者调用此方法向用户显示数据
}

//天气数据
class WeatherData extends Observable{
    private double temperature;
    private double humidity;
    private double pressure;

    WeatherData() {}

    //向观察者发送数据
    public void measurementsChanged() {
        setChanged();		//向观察者发送数据之前必须先调用这个,表示数据已经更新,change=true
        notifyObservers();	//个人认为notifyObservers()会自动调用ConditionDisplay类的update()方法
    }

    //从数据源收到数据后,是先更新自己的数据,再把数据发给观察者
    void setMeasurements(double temp,double humidity,double pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
    //留出接口给观察者获取数据
    double getTemperature() {
        return temperature;
    }

    double getHumidity() {
        return humidity;
    }

    double getPressure() {
        return pressure;
    }
}

class ConditionDisplay implements Observer,DisplayElement{
    private double temperature;
    private double humidity;
    private double pressure;
    private Observable observable;//任何数据源的引用

    //当构建观察者时,必须指定其 数据源
    ConditionDisplay(Observable observable,String name) {
        this.observable = observable;
        observable.addObserver(this);//注册
    }

    public void display() {
        System.out.println("temperature:"+temperature+"  humidity:"+humidity+"  pressure:"+pressure);
    }
    //更新方法,
    public void update(Observable o, Object arg) {
        if(o instanceof WeatherData) {
            WeatherData w = (WeatherData)o;//向下转型调用天气数据类的方法
            this.temperature = w.getTemperature();
            this.humidity = w.getHumidity();
            this.pressure = w.getPressure();
            display();//展示数据
        }
    }
}

class WeatherStation {

    public static void main(String[] args) {
        /*数据源和观察者都要维护一个 中介角色WeatherData*/
        WeatherData weatherdata = new WeatherData();

        ConditionDisplay cd1 = new ConditionDisplay(weatherdata,"ob1");

        /*数据源获得数据,并调用WeatherData的方法,来向WeatherData 写数据*/
        weatherdata.setMeasurements(10.5, 10.4, 10.8);
        weatherdata.setMeasurements(10.2, 10.1, 10.6);
    }
}

参考博文:https://blog.csdn.net/u014453898/article/details/79167927

举报

相关推荐

0 条评论