您的位置:首页 > 其它

设计模式之观察者模式

2016-02-24 21:23 218 查看
想要建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况,气象统计,和天气预报。

最原始的代码

WeatherData

getTemperature()

getHumidity()

getPressure();

Measure-

mentsChanged()

 

//一旦气象测量更新,此方法会被调用

Public void measurementsChanged(){

 

}

 

现在了解的信息有:

WeatherData类具有getter方法 可以取得三个测量值

 

当测量数据准备好时,measurementsChanged()方法会调用

 

实现三个使用天气数据的布告板:目前状况布告板,气象统计布告板,天气预报布告板,

一旦WeatherData有新的测量,这些布告板马上更新

 

此系统必须可扩展,让其它开发人员建立定制的布告板,用户可以随心所欲添加删除任何布告板.目前布告板有三类:目前状况布告板 气象统计布告板 天气预报布告板.

 

第一种实现:

Public class WeatherData{

Public void meausrementsChanged(){

Float temp = getTemperature();

Float humidity = getHumidity();

Float pressure = getPressure();

 

currentConditionDisplay.update(temp,humidity,pressure);

statisticsDisplay.update(temp,humidity,pressure);

forecastDiaplay.update(temp,humidity,pressure);

 

}

}

布告板更新代码是针对具体实现编程,导致以后增加删除布告板时必须修改程序.

Update方法具有相似性,看起来像一个统一的接口。

 

观察者模式就好像报社与订报纸的用户之间的关系:

用户向报社预定报纸,报社有新报纸就会给用户发报纸,当用户订阅取消时候,报社就不会给用户发报纸.

在观察者模式中 报社相当于Subject 订阅者为Observer

当主题内的数据改变时候,就会通知观察者。

 

观察者模式:

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

 

 

Subject接口具有registerObserver() removeObserver() notifyObservers();

 

Observer接口 具有方法:update()

 

主题具有状态,可以控制这些状态,观察者使用这些状态,观察者依赖主题告诉他们状态何时改变了。

产生了一个主题对多个观察者的的关系。

 

接下来实现气象站的代码

主题接口:

public interface Subject {

    public void registerObserver(Observer o);

    public void removeObserver(Observer o);

    public void notifyObserver();

}

观察者接口

public interface Observer {

    public void update(float temp,float humidity,float pressure);

}

显示接口:

public interface DisplayElement {

    public void display();

}

气象数据实现主题接口 作为主题 提供数据

public class WeatherData implements Subject {

    private ArrayList observers;

    private float temperature;

    private float humidity;

    private float pressure;

    public WeatherData(){

        observers = new ArrayList();

    }

    @Override

    public void registerObserver(Observer o) {

        observers.add(o);

    }

 

    @Override

    public void removeObserver(Observer o) {

        int i = observers.indexOf(o);

        if(i >= 0){

            observers.remove(i);

        }

    }

 

    //閫氱煡瑙傚療鑰�

    @Override

    public void notifyObserver() {

        for(int i = 0; i < observers.size(); i++){

            Observer observer = (Observer)observers.get(i);

            observer.update(temperature,humidity,pressure);

        }

    }

 

    //数据获取来源

    public void setMeasurements(float temperature,float humidity,float pressure){

        this.temperature = temperature;

        this.humidity = humidity;

        this.pressure = pressure;

        measurementsChanged();

    }

 

    //通知用户更新数据

    public void measurementsChanged(){

        notifyObserver();

    }

}

 

 

 

 

/**

 * Created by Administrator on 2016/2/24.

 */

显示类 实现Observer 作为一个观察者 获取主题的数据

public class CurrentConditionDisplay implements Observer,DisplayElement {

    private float temperature;

    private float humidity;

    private Subject weatherData;//保存WeatherData 为了取消注册时用

 

 

    public CurrentConditionDisplay(Subject weatherData){

        this.weatherData = weatherData;

        weatherData.registerObserver(this);

    }

    @Override

    public void display() {

        System.out.println("Current conditions: "+ temperature+"F degrees and" + humidity+" %humidity");

    }

 

    @Override

    public void update(float temp, float humidity, float pressure) {

        this.temperature = temp;

        this.humidity = humidity;

        display();

    }

}

 

//测试程序

public class MyClass {

    public static void main(String[] args){

        WeatherData weatherData = new WeatherData();

        CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);

        weatherData.setMeasurements(10,10,10);

        weatherData.setMeasurements(20,20,20);

        weatherData.setMeasurements(20,20,30);

    }

}

 

这种方式属于推数据 主题将数据全都给观察者,不管观察者需不需要

 

还有java sdk 自带观察者类,Observable 主题类

Observer接口 观察者.

Java 自带可以实现 拉数据,观察者可以获得自己想要的数据.

主题类的实现:

package com.gac;

 

import java.util.Observable;

 

public class WeatherData extends Observable{

    private float temperature;

    private float humidity;

    private float pressure;

    

    

    public WeatherData(){

    

    }

    

    public void measurementsChanged(){

    //下面的方法都是继承来的 

    setChanged();//调用notify之前 使用setChanged指示状态已经改变

    notifyObservers();//采用拉的方式获取数据 观察者可以获得自己想要的数据

    }

    

    //数据获取来源

    public void setMeasurements(float temperature,float humidity,float pressure){

        this.temperature = temperature;

        this.humidity = humidity;

        this.pressure = pressure;

        measurementsChanged();

    }

 

    //使用拉获取数据时候需要 get方法

public float getTemperature() {

return temperature;

}

 

public float getHumidity() {

return humidity;

}

 

public float getPressure() {

return pressure;

}

 

}

 

 

package com.gac;

 

import java.util.Observable;

import java.util.Observer;

//观察者类

public class CurrentConditionDisplay  implements Observer,DisplayElement{

 

private Observable observable;

private float temperature;

private float humidity;

public CurrentConditionDisplay(Observable observable){

this.observable = observable;

observable.addObserver(this);

}

@Override

public void display() {

// TODO Auto-generated method stub

 System.out.println("Current conditions: "+ temperature+"F degrees and" + humidity+" %humidity");

}

 

@Override

public void update(Observable o, Object arg) {

// TODO Auto-generated method stub

if(o instanceof WeatherData){

WeatherData weatherData = (WeatherData)o;

this.temperature = weatherData.getTemperature();

this.humidity = weatherData.getHumidity();

display();

}

}

 

}

 

测试程序

package com.gac;

 

 

public class MyClass {

    public static void main(String[] args){

        WeatherData weatherData = new WeatherData();

        CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);

        weatherData.setMeasurements(10,10,10);

        weatherData.setMeasurements(20,20,20);

        weatherData.setMeasurements(30,30,30);

    }

}

 

总结:

面向对象的基础是:抽象

面向对原则:

封装变化

多用组合,少用继承

针对接口编程,不针对实现编程

为交互对象之间的松耦合设计而努力。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: