设计模式之观察者模式
观察者者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,所有的依赖者都会收到通知并及时更新。
举一个气象观察站的例子:假如有一个气象站可以检测温度,湿度,气压,现在要把这些数据全部传送到三块显示板上,气象站是一,三块显示板是多,最容易想到的方案是定义一个气象站类WeatherData,在类里面写一个方法,把数据分别传送给三个显示板,如下所示:
public class WeatherData { //实例变量声明 public void measurementChanged() { //取得最近的测量值 float temp = getTemplature(); float humidity = getHumidity(); float pressure = getPressure(); //更新显示板 currentConditionsDisplay.update(temp, humidity, pressure); statisticsDisplay.update(temp, humidity, pressure); forecastDisplay.update(temp, humidity, pressure); } }
上面的方式是针对的具体实现编程,所以如果要增加显示板或者减少显示板,那么上面的程序就要修改,显示板和气象站耦合在一起,这样不利于扩展。下面利用观察者模式来解决这个问题。
//主题接口 public interface Subject { public void registerObserver(Observer o); //注册观察者 public void removeObserver(Observer o); //移除观察者 public void notifyObservers(); //通知观察者 } //观察者接口 public interface Observer { public void update(float temp, float humidity, float pressure); //更新数据 } //显示数据接口 public interface DisplayElement{ public void display(); } //气象站 public class WeatherData implements Subject { private ArrayList observers; //保存观察者的ArrayList 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 measurementChanged() { //数据改变时通知观察者 notifyObservers(); } } //观察者 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); } public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); } public void display() { System.out.println("Current conditions:" + temperature + "F degrees and" + humidity + "%humidity"); } }
这样,当我们要扩展程序增加观察者时,只需写一个实现了Observer, DisplayElement接口的类就可以了,原程序不需要改动。