观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者模式的结构:
主要有四部分:主题接口、观察者接口、具体主题、具体观察者。
举个例子: 气象观测站项目。WeatherData对象获取观测数据,另外有三个布告板类,分别显示目前状况、气象统计和天气预报。当WeatherData对象获取到最新数据时,三个布告板必须实时更新。以后会出新的布告板。
先看主题接口代码和观察者接口代码,只是简单的声明三个方法:
//主题接口
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);
}
具体主题(WeatherData)实现代码:
主题类需要一个集合类来保存已经存在的观察者们,当新数据到来时,遍历观察者集合并将新数据作为参数调用每一个观察者的update()方法。注册方法和删除方法实现很简单,简单的将作为参数的观察者添加到集合类或从集合类中去除即可。
public class WeatherData implements Subject{
//使用ArrayList集合类保存当前的所有观测者
private ArrayList observers = new ArrayList();
private float temp,humidity,pressure; //要采集的数据
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 notifyObserver(){//把状态告知所有观察者
//遍历观察者集合,调用每个观察者的update方法
for(int i=0;i<observers.size();i++){
Observer observer = (Observer) observers.get(i);
observer.update(temp,humidity, pressure);
}
}
//模拟实时获取到数据,进行更新
public void setMeasurements(float temp,float humidity,float pressure){
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
notifyObserver();
}
}
其中一个观察者(布告板)实现代码:
观察者类需持有一个主题类的引用。想要将改观察者加入主题中,则将相关主题对象传入方法中,方法中使用该主题对象添加自己即可。
public class CurrentConditionsDisplay implements Observer{
private float temp, humidity;
WeatherData weatherData;
//构造器需要weatherData对象(也就是主题)作为注册之用。
public CurrentConditionsDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temp,float humidity,float pressure){
this.temp = temp;
this.humidity = humidity;
display();
}
}
观察者模式的两种实现:
java内置支持“拉”和“推”两种观察者模式,需要引入两个包:
import java.util.Observable;
import java.util.Observer;