观察者模式
观察者模式:
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象状态被修改时,其他依赖者都会收到通知。观察者模式属于行为型模式。
例子:
如下图所示,此例子有三个部分:气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)、布告板(显示目前天气状况给用户看)。
当WeatherData获得最新天气数据时,三种布告板实时更新。
设计气象站:
代码实现:
三个需要实现的接口:
public interface Subject { /** * 注册观察者 * @param o */ public void registerObserver(Observer o); /** * 移除观察者 * @param o */ public void removeObserver(Observer o); /** * 状态改变时,通知所有观察者 */ public void notifyObserver(); } public interface Observer { public void update(float temp, float humidity, float pressure); } public interface DisplayElement { /** * 显示方法 */ public void display(); }
WeatherData类实现:
public class WeatherData implements Subject { private ArrayList observers; /** * 温度 */ private float temperature; /** * 湿度 */ private float humidity; /** * 气压 */ private float pressure; public WeatherData(){ observers = new ArrayList(); } @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 = (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(); } }
布告栏类:
1 public class CurrentConditionDisplay implements Observer, DisplayElement{ 2 private float temperature; 3 private float humidity; 4 private Subject weatherData; 5 6 public CurrentConditionDisplay(Subject wd){ 7 this.weatherData = wd; 8 weatherData.registerObserver(this); 9 } 10 11 @Override 12 public void update(float temp, float humidity, float pressure) { 13 this.temperature = temp; 14 this.humidity = humidity; 15 display(); 16 } 17 18 @Override 19 public void display() { 20 System.out.println("current conditions(目前天气状况): " + temperature 21 + "F degrees and " + humidity + "% humidity"); 22 } 23 }
其他两个布告栏类似
测试类:
1 public class WeatherStationMain { 2 3 public static void main(String[] args){ 4 WeatherData weatherData = new WeatherData(); 5 CurrentConditionDisplay ccd = new CurrentConditionDisplay(weatherData); 6 StatisticsDisplay sd = new StatisticsDisplay(weatherData); 7 ForecastDisplay fd = new ForecastDisplay(weatherData); 8 9 weatherData.setMeasurements(80, 70, 20.4f); 10 System.out.println(); 11 weatherData.setMeasurements(60, 83, 30.7f); 12 } 13 }
自定义的observer已经完成,java提供了自己的观察者模式。
Java内置观察者模式:
1、如何把对象变成观察者
实现观察者接口(java.uitl.Observer),然后调用Observable对象的addObserver()方法。不想在当观察者了,调用deleteObserver()方法。
2、观察者如何发送通知
首先,需要实现java.util.Observable接口,产生“可观察者”类,然后,需要两个步骤:
(1)先调用setChanged()方法,标记状态已经改变的事实。
(2)然后调用两种notifyObservers()方法中的一个:拉方式:notifyObservers() 、 推方式:notifyObservers(Object arg)
3、观察者如何接收通知
实现观察者接口(java.uitl.Observer),实现更新方法update(Observable o, Object arg),arg参数内容为notifyObservers(Object arg)推送的数据。
Java内置观察者模式具体实现代码可参考我的github上的实现:https://github.com/oshua/design-pattern
注意:java内置模式的缺点,Observable是一个类:如果想同时具有Observable和另一个超类的行为,不能实现,因为Java不支持多重继承,这就限制了Observable的复用潜力。