观察者模式定义了对象间的一对多的依赖关系,主题有状态,发生改变会通知观察者,比较好的例子如报纸订阅,主要目的是实现松耦合.
另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内置的观察者模式,不用自己定义Observer和Subject 接口。
分析:所以观察者模式其实很简单,就是将主题和观察者分开,减少以来,主题不用新谁需要我,也不需要知道该通知谁,都在运行时完成。还是重复我们的OO设计原则,可复用,可维护,减少依赖。