把對象變成觀察者:實現觀察者接口(java.util.Observer),而後調用Observable對象的addObserver()方法或deleteObserver()java
可觀察者送出通知:ide
一、擴展java.util.Observable類產生"可觀察者"類測試
2 、1)先調用Observable的setChanged()方法,標記主題的狀態已經改變,讓notifyObservers()知道當它被調用時應該更新觀察者,若是調用notifyObservers()以前沒有調用setChanged(),觀察者就不會被通知更新。this
Observable的setChanged()方法(修飾符是protected,不能建立Observable實例並組合到本身的對象中由於不能使用setChanged()方法,除非繼承Observable類):code
protected synchronized void setChanged() { changed = true; }
2)調用兩種notifyobservers()方法中的一個:server
notifyobservers()或notifyobservers(Object arg)對象
java.util.Observable的notifyobservers(Object arg)的方法:繼承
Object arg:當通知時,能夠把arg(數據對象data object)經過update方法傳送給每個觀察者接口
public void notifyObservers(Object arg) { Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); }
java.util.Observable的notifyobservers()方法:rem
public void notifyObservers() { notifyObservers(null); }
觀察者如何接收通知:
觀察者實現了跟新的方法:
update(Observable o,Object arg)
Observable o:主題自己看成第一個變量,好讓觀察者知道是哪一個主題通知它的
Object arg:是傳入notifyobservers()的數據對象,若是沒有則說明爲空。
若是想"推"(push)數據給觀察者,能夠把數據看成數據對象傳送給notifyobservers()方法。不然,觀察者必須從可觀察者對象中"拉"(pull)數據。
下面經過觀察者從可觀察者處拉數據的演示:
一、把WeatherData改爲使用java.util.Observable
package com.ya; import java.util.ArrayList; import java.util.Observable; public class WeatherData extends Observable{ private float temperature; private float humidity; private float pressure; public WeatherData(){ } public void measurementsChanged(){ //調用notifyObservers()方法以前先調用setChanged() setChanged(); //若是該方法的參數沒有Object數據對象,這表示採用的是觀察者主動向可觀察者"拉"的方式 notifyObservers(); } public void setMeasurements(float temperature,float humidity,float pressure){ this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } //下面三個方法,由於咱們要使用"拉"的作法,觀察者會利用這些方法得到WeatherData對象的狀態 public float getTemperature(){ return temperature; } public float getHumidity(){ return humidity; } public float getPressure(){ return pressure; } }
CurrentConditionsDisplay佈告板:
package com.ya; import java.util.Observable; import java.util.Observer; public class CurrentConditionsDisplay implements Observer,DisplayElement{ Observable observable; private float temperature; private float humidity; private float pressure; public CurrentConditionsDisplay(Observable observable) { this.observable = observable; observable.addObserver(this); } @Override public void update(Observable obs, Object obj) { if(obs instanceof WeatherData){ WeatherData weatherData = (WeatherData)obs; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } display(); } public void display(){ System.out.println("Current conditions:" + temperature + "F degrees and"+ humidity +" %humidity"); } }
測試代碼類WeatherStation:
package com.ya; public class WeatherStation { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); } }
有多個公佈板時(觀察者),測試結果每次輸出的次序不同,而自定義觀察者的模式輸出次序每次輸出都同樣。
這是由於java.util.Observable實現了notifyObservers()方法,調用觀察者的update的次序與自定義的觀察者模式不同。
//java內置的可觀察者調用觀察者的update的次序是後加入的先調用 for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); //自定義的觀察者模式調用觀察者的update的次序是先加入的先調用 for(int i=0;i<observers.size();i++){ Observer observer = (Observer)observers.get(i); observer.update(temperature,humidity,pressure); }
在JDK中,不是隻有java.util中才能找到觀察者模式,在JavaBeans和Swing中,也都實現了觀察者模式。