观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
体现新的OO原则: 为交互对象之间的松耦合设计而努力。
类图:
- 主题接口
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
- 观察者接口
public interface Observer {
public void updata(float temp, float humidity, float pressure);
}
- 具体主题
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData(){
observers = new ArrayList();
}
public void measurementsChanged(){
notifyObserver();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
@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 = observers.get(i);
observer.updata(temperature, humidity, pressure);
}
}
}
- 具体观察者
public class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private Subject weartherData;
public CurrentConditionsDisplay(Subject weartherData) {
this.weartherData = weartherData;
//注册
weartherData.registerObserver(this);
}
@Override
public void updata(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
//do something
}
}
当然关于观察者模式,还存在”拉”和”推”一说,其实上面的例子就是”推”的例子,可以在一次通知中得到所有东西,上面的例子就是在一次通知将温度(temp)、湿度(humidity)和气压(pressure)全部得到,如果采用”拉”的方式就是三个get和set方法,每次可以”拉”走你需要的状态。
java 内置观察者模式
使用 java.util.Observable 和 java.util.Observer 实现观察者。可以使用推push或拉pull的方式传送数据。
类图:
- 可观察者
import java.util.Observable;
public class MWeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public MWeatherData(){}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public void measurementsChanged(){
//在调用notifyObservers之前,需要先调用setChanged指示状态以改变
setChanged();
//没有在参数里面传递数据,表示观察者自己拉数据
notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
- 具体观察者
import java.util.*;
public class MCurrentConditionDisplay implements java.util.Observer {
Observable observable;
private float temperature;
private float humidity;
public MCurrentConditionDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable observable, Object data) {
if (observable instanceof MWeatherData){
MWeatherData mWeatherData = (MWeatherData) observable;
this.temperature = mWeatherData.getTemperature();
this.humidity = mWeatherData.getHumidity();
//do something
}
}
}
注意:
- java.util.Observable 的实现有许多问题,限制了它的使用和复用。
- Observable 是一个类,不是一个接口,java是只支持单继承的,限制了Observable的复用。
- Observable 中 setChanged() 方法时 protected 的。