源码分析
Java内置观察者模式使用了一个类 Observable,一个接口 Observer
分析类 Observable
private boolean changed = false; private Vector<Observer> obs; /** Construct an Observable with zero Observers. */ public Observable() { obs = new Vector<>(); }
notifyObservers()和notifyObservers(Object)依赖于 changed的状态,判断changed状态来决定观察者是否update,
在更新完成后clearChanged();
/** * If this object has changed, as indicated by the * <code>hasChanged</code> method, then notify all of its observers * and then call the <code>clearChanged</code> method to * indicate that this object has no longer changed. * <p> * Each observer has its <code>update</code> method called with two * arguments: this observable object and <code>null</code>. In other * words, this method is equivalent to: * <blockquote><tt> * notifyObservers(null)</tt></blockquote> * * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void notifyObservers() { notifyObservers(null); } /** * If this object has changed, as indicated by the * <code>hasChanged</code> method, then notify all of its observers * and then call the <code>clearChanged</code> method to indicate * that this object has no longer changed. * <p> * Each observer has its <code>update</code> method called with two * arguments: this observable object and the <code>arg</code> argument. * * @param arg any object. * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void notifyObservers(Object arg) { /* * a temporary array buffer, used as a snapshot of the state of * current Observers. */ Object[] arrLocal; synchronized (this) { /* We don't want the Observer doing callbacks into * arbitrary code while holding its own Monitor. * The code where we extract each Observable from * the Vector and store the state of the Observer * needs synchronization, but notifying observers * does not (should not). The worst result of any * potential race-condition here is that: * 1) a newly-added Observer will miss a * notification in progress * 2) a recently unregistered Observer will be * wrongly notified when it doesn't care */ if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); }特别注意notifyObserveres(Object)方法
1、arrLocal数组对象的作用-临时缓存,用于存储Observers的快照
2、sychronized(this)同步处理会导致两个问题,新加入的Observer对象不会通知,最近的unregistered对象仍会执行通知
实例说明
1、对象如何变成观察者
通过实现Observer接口,然后调用Observable对象的addObserver();
package org.watt.thinkinginjava.observer.java; import java.util.Observable; import java.util.Observer; public class CurrentConditionDisplay implements Observer, DisplayElement { private float temperature; private float humidity; private float pressure; private Observable observable; public CurrentConditionDisplay(Observable observable) { this.observable = observable; observable.addObserver(this); } public void display() { System.out.println("CurrentConditionDisplay: " + temperature + " ," + humidity + ", " + pressure); } public void update(Observable o, Object arg) { if (o instanceof WeatherData) { WeatherData weatherData = (WeatherData) o; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } } }
2、可观察者如何送出通知
可观察者继承Observable对象通过设置change状态
package org.watt.thinkinginjava.observer.java; import java.util.Observable; public class WeatherData extends Observable { private float temperature; private float humidity; private float pressure; public void measurementsChanged() { //设置changed标识状态 setChanged(); notifyObservers(); } public void setMeasurements(float temperature, float humidity, float pressure) { this.setTemperature(temperature); this.setHumidity(humidity); this.setPressure(pressure); measurementsChanged(); } public float getTemperature() { return temperature; } public void setTemperature(float temperature) { this.temperature = temperature; } public float getHumidity() { return humidity; } public void setHumidity(float humidity) { this.humidity = humidity; } public float getPressure() { return pressure; } public void setPressure(float pressure) { this.pressure = pressure; } }
3、观察者如何接收通知
观察者实现update方法
public void update(Observable o, Object arg) { //从WeatherData中获取数据 if (o instanceof WeatherData) { WeatherData weatherData = (WeatherData) o; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } }
Observable用来定位是哪个主题通知你的,也可以把数据当作数据对象传给notifyObservers(args),在调用update时传入
public void update(Observable o, Object arg) { //传入对象中获取
WeatherData weatherData = (WeatherData) arg; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display();}
总结
1、内置观察者模式Obserable是个对象,一般情况下是面向接口编程,这个比较特别,而且setChanged等方法是protected,只有继承才能使用控制观察者对象;
2、Observer接口方法的使用,可以通过两种方式来传递数据,一种是继承Obserable生成的对象,另一种是使用update的第二个参数传入。