观察者模式定义了对象间的一对多的依赖关系,主题有状态,发生改变会通知观察者,比较好的例子如报纸订阅,主要目的是实现松耦合.

 

   JAVA提供了内置的观察者模式. JAVA.util包里的OBSERVER 接口和OBSERVABLE,不同的是主题是OBSERABLE 是一个类,里面提供了对观察者的管理\注册\注销\状态管理.只要继承这个类就可以.

 

    观察者模式主要应用就是 一个主题提供各种信息,需要的人为观察者,可以通过推或拉的方式获取消息,另外可以扩展信息过滤.JAVA包中有很多类都采用该机制,JBUTTTON,事件的管理和注册.

 

     例子:天气预报(没有采用JAVA内置的观察者模式)

     Subject 主题接口

     代码如下:

   public interface Subject {

      public void registerObserver(Observer o); //观察者注册

      public void removeObserver(Observer o);   //删除观察者

      public void notifyObservers();            //通知观察者

     }

     主题实现类 WeatherData  实现主题接口,并实现其方法.

   public class WeatherData implements Subject {

    private ArrayList observers;

    private float temperature;

    private float humidity;

    private float pressure;

   

    public WeatherData() {

       observers = new ArrayList();

    }

   

    public void registerObserver(Observer o) {

       observers.add(o);

    }

   

    public void removeObserver(Observer o) {

       int i = observers.indexOf(o);

       if (i >= 0) {

           observers.remove(i);

       }

    }

   

    public void notifyObservers() {

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

           Observer observer = (Observer)observers.get(i);//观察者

           observer.update(temperature, humidity, pressure);//观察者更新  }

    }

   

    public void measurementsChanged() {

       notifyObservers();

    }

   

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

       this.temperature = temperature;

       this.humidity = humidity;

       this.pressure = pressure;

       measurementsChanged();

    }

   

    // other WeatherData methods here

   

    public float getTemperature() {

       return temperature;

    }

   

    public float getHumidity() {

       return humidity;

    }

   

    public float getPressure() {

       return pressure;

    }

}

观察者接口 用于更新状态

public interface Observer {

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

}

显示接口-用于根据不同需求显示不同的天气数据

public interface DisplayElement {

    public void display();

}

天气预报显示类,实现了观察者接口和显示接口;

public class ForecastDisplay implements Observer, DisplayElement {

    private float currentPressure = 29.92f; 

    private float lastPressure;

    private WeatherData weatherData;

 

    public ForecastDisplay(WeatherData weatherData) {

       this.weatherData = weatherData;

       weatherData.registerObserver(this);

    }

 

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

                lastPressure = currentPressure;

       currentPressure = pressure;

 

       display();

    }

 

    public void display() {

       System.out.print("Forecast: ");

       if (currentPressure > lastPressure) {

           System.out.println("Improving weather on the way!");

       } else if (currentPressure == lastPressure) {

           System.out.println("More of the same");

       } else if (currentPressure < lastPressure) {

           System.out.println("Watch out for cooler, rainy weather");

       }

    }

}

天气预报站

public class WeatherStation {

    public static void main(String[] args) {

       WeatherData weatherData = new WeatherData();

        ForecastDisplay forecastDisplay= new ForecastDisplay(weatherData);

       weatherData.setMeasurements(80, 65, 30.4f);

      

    }

}

 

我们也可以利用Java内置的观察者模式,同样实现的代码如下:

import java.util.Observable;

import java.util.Observer;

   

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;

    }

}

Observable负责完成观察者的管理、注册和注销、通知。

import java.util.Observable;

import java.util.Observer;

 

public class ForecastDisplay implements Observer, DisplayElement {

    private float currentPressure = 29.92f; 

    private float lastPressure;

 

    public ForecastDisplay(Observable observable) {

       observable.addObserver(this);

    }

 

    public void update(Observable observable, Object arg) {

       if (observable instanceof WeatherData) {

           WeatherData weatherData = (WeatherData)observable;

           lastPressure = currentPressure;

           currentPressure = weatherData.getPressure();

           display();

       }

    }

 

    public void display() {

       System.out.print("Forecast: ");

       if (currentPressure > lastPressure) {

           System.out.println("Improving weather on the way!");

       } else if (currentPressure == lastPressure) {

           System.out.println("More of the same");

       } else if (currentPressure < lastPressure) {

           System.out.println("Watch out for cooler, rainy weather");

       }

    }

}

其他出五变化,主要是利用了JAVA内置的观察者模式,不用自己定义ObserverSubject 接口。

 

分析:所以观察者模式其实很简单,就是将主题和观察者分开,减少以来,主题不用新谁需要我,也不需要知道该通知谁,都在运行时完成。还是重复我们的OO设计原则,可复用,可维护,减少依赖。