观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
- 观察者模式定义了对象之间的一对多关系。
- 主题(也就是观察者)用一个共同的接口来更新观察者
- 观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口。
- 使用此模式时,你可从被观察者处推(push)或(pull)数据(然而,推的方式被认为更“正确”)。
- 有多个观察者时,不可以依赖特定的通知次序。
- Java有多种观察者模式的实现,包括了通用的java.util.Observable。
- 要注意java.util.Observable实现上所带来的一些问题。
- 如果有必要的话,可以实现自己的Observable,这样不难,不要害怕。
- Swing大量使用观察者模式,许多GUI框架也是如此。
- 此模式也被应用在许多地方,例如:JavaBeans、RMI。
/** * 主题接口,对象通过次接口定义观察者,或者把自己从观察者中删除 */ public interface Subject { /** * 注册主题 */ void registerObserver(Observer o); /** * 删除主题 */ void removeObserver(Observer o); /** * 主题改变时,此方法调用,以通知所有观察者 */ void notifyObserver(); }
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 notifyObserver() { for (int i = 0; i < observers.size(); i++) { Observer observer = (Observer) observers.get(i); observer.update(temperature,humidity,pressure); } } public void measurementsChanged(){ notifyObserver(); } public void setMeasurements(float temperature,float humidity,float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } }
public class CurrentConditionsDisplay implements Observer,DisplayElement{ private float temperature; private float humidity; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } //此方法调用时,我们把温度和湿度保存起来,然后调用display() public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; display(); } public void display() { System.out.println("Current conditions:"+temperature+" F degrees and "+ humidity + "% humidity"); } }
/** * 布告板 */ public interface DisplayElement { /** * 布告板显示时,调用此方法 */ void display(); }
/** * 观察者 */ public interface Observer { /** * 当气象观测值改变时,主题会把这些状态值当作方法参数,传递给观察者 * @param temp * @param humidity * @param pressure */ void update(float temp,float humidity,float pressure); }
public class Ch2Test { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80,65,30.4f); weatherData.setMeasurements(82,70,29.2f); weatherData.setMeasurements(78,90,29.2f); } }