創建一個氣象站應用, 利用WeatherData對象取得數據,並更新三個佈告板: 目前情況 , 氣象統計 , 天氣預報java
此係統中的三個部分是氣象站(獲取實際氣象數據的物理裝置) , WeatherData對象(追蹤來自氣象站的數據,並更新佈告板) 和 佈告板(顯示目前天氣情況給用戶看.)git
WeatherData對象知道如何跟物理氣象站聯繫,以取得更新的數據.WeatherData對象會隨即更新三個佈告板的顯示: 目前情況(溫度 , 溼度 , 氣壓), 氣象統計和天氣預報github
//WeatherData構造函數 , 當新公告板加入時, 也要跟着改變 public WeatherData(CurrentConditionsDisplay currentConditionsDisplay, StatisticsDisplay statisticsDisplay,ForecastDisplay forecastDisplay) { this.currentConditionsDisplay = currentConditionsDisplay; this.statisticsDisplay = statisticsDisplay; this.forecastDisplay = forecastDisplay; }
分析可變部分設計模式
定義:在
對象之間定義一對多的依賴
,這樣一來, 當一個對象改變狀態,依賴它的對象都會收到通知,並自動更新
模式的理解函數
角色學習
管理某些數據
, 當主題內的數據改變時 , 就會通知觀察者
訂閱
主題, 以便在主題數據改變時能收到更新 , 當不想訂閱主題時,也能隨時移除訂閱
細節this
觀察者模式 對數據推送有兩種方式 推(push)和拉(pull)
spa
推送方式:設計
拉取方式code
觀察者模式提供了一種對象設計,讓主題和觀察者之間鬆耦合
主題
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); }
WeatherData
public class WeatherData implements Subject { private ArrayList<Observer> observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList<Observer>(); } 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() { //遍歷全部的觀察者,調用update方法 for (Observer observer : observers) { observer.update(temperature, humidity, pressure); } } public void measurementsChanged() { notifyObservers(); } //氣象站數據改變時調用的方法 public void setMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; measurementsChanged(); } //其餘的get方法 }
觀察者--今日佈告板
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"); } }
主程序 ----主題數據改變
public class WeatherStationHeatIndex { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); weatherData.setMeasurements(80, 65, 30.4f); weatherData.setMeasurements(82, 70, 29.2f); weatherData.setMeasurements(78, 90, 29.2f); } }
輸出結果
Current conditions: 80.0F degrees and 65.0% humidity Avg/Max/Min temperature = 80.0/80.0/80.0 Forecast: Improving weather on the way! Current conditions: 82.0F degrees and 70.0% humidity Avg/Max/Min temperature = 81.0/82.0/80.0 Forecast: Watch out for cooler, rainy weather Current conditions: 78.0F degrees and 90.0% humidity Avg/Max/Min temperature = 80.0/82.0/78.0 Forecast: More of the same
java.util.Observer
使用
可觀察者(主題)送出通知
調用setChanged()方法, 標記數據已改變
setChanged(){ changed = true; } notifyObservers(Object arg){ if(changed){ //只有當changed爲true時才進行通知 for every observer on the list{ call update(this,arg) } changed = false; //通知觀察者後,將changed設置爲false } } notifyObservers(){ notifyObservers(null); }
調用notifyObservers() 通知全部觀察者
觀察者接收通知
public void update(Observable obs, Object arg) { if (obs instanceof WeatherData) { WeatherData weatherData = (WeatherData)obs; this.temperature = weatherData.getTemperature(); this.humidity = weatherData.getHumidity(); display(); } }
書籍: HeadFirst設計模式
代碼參考地址: 我就是那個地址