上一篇講解完天氣監測系統的大致架構,接下來看一下程式碼的部分~
(完整程式碼點我)
首先是觀察者的介面,可以更新天氣資訊。
public interface Observer{
public void update(float temp, float humidity, float pressure);
}
主體的介面,會包含註冊、移除、通知訂閱者的方法。
public interface Subject{
public void registerObservers(Observer obr);
public void removeObservers(Observer obr);
public void notifyObservers();
}
用天氣資訊類別去實作主題介面,ArrayList<Observer> observers
是紀錄主題有哪些訂閱者的陣列,
透過陣列的新增移除來實現註冊和移除訂閱者的方法。天氣資料更改會使用 setMeasurements()
,接著會呼叫measurementsChanged()
,它會再呼叫 notifyObservers()
去實際更新天氣資訊讓每個訂閱者知道。
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 registerObservers(Observer obr){
observers.add(obr);
}
public void removeObservers(Observer obr){
int id = observers.indexOf(obr);
if(id >= 1){
observers.remove(id);
}
}
public void notifyObservers(){
for(int i = 0; i < observers.size(); i++){
Observer obr = (Observer)observers.get(i);
obr.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();
}
}
顯示裝置的介面 DisplayElement()
public interface DisplayElement{
public void display();
}
系統包含三種顯示模式,顯示模式會實作訂閱者以及顯示裝置的介面。
首先是最新資料顯示模式 CurrentConditionDisplay()
,當 WeatherData 呼叫 notifyObservers()
時,WeatherData 透過迴圈以 update()
一一通知訂閱者資料已經更新,再用 display()
展示。
public class CurrentConditionDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObservers(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 + " degree / Humidity:" + humidity );
}
}
第二種為天氣預報模式 ForecastDisplay()
public class ForecastDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public ForecastDisplay(Subject weatherData){
this.weatherData = weatherData;
weatherData.registerObservers(this);
}
public void update(float temperature, float humidity, float pressure){
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display(){
System.out.println("Tomorrow Weather : " + temperature + " degree / Humidity:" + humidity );
}
}
第三種是天氣資料統計模式,用來計算平均溫度、最高溫、最低溫,每次資料更新後,就會用tempSum
加總之前的資料,重新再計算一次正確的數值。
public class StatisticDisplay implements Observer, DisplayElement {
private float maxTemp = 0.0f;
private float minTemp = 200;
private float tempSum= 0.0f;
private int numReadings;
private WeatherData weatherData;
public StatisticDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObservers(this);
}
public void update(float temp, float humidity, float pressure) {
tempSum += temp;
numReadings++;
if (temp > maxTemp) {
maxTemp = temp;
}
if (temp < minTemp) {
minTemp = temp;
}
display();
}
public void display() {
System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
+ "/" + maxTemp + "/" + minTemp);
}
}
來實際跑一次,手動模擬新的天氣資料被寫入
public class WeatherStation{
public static void main(String[] string){
WeatherData curData = new WeatherData();
CurrentConditionDisplay c = new CurrentConditionDisplay(curData);
StatisticDisplay s = new StatisticDisplay(curData);
curData.setMeasurements(32,65,30.4f);
curData.setMeasurements(30, 92, 20.4f);
WeatherData forecastData = new WeatherData();
ForecastDisplay f = new ForecastDisplay(forecastData);
forecastData.setMeasurements(27,74,45f);
curData.setMeasurements(34, 55, 32.9f);
}
}
最後輸出:
小碎念( •́ὤ•̀)
本來以為統計資料也要包含濕度、氣壓,害我超苦惱要怎麼寫,結果到書中附的程式碼一看發現是個簡單粗暴的答案⋯⋯
第一次參加這種活動,發現寫文章比我想的難好多,所以我超謹慎地一直查資料,很怕寫錯會誤導別人(瘋掉)
雖然整體應該看得出來我很菜,不過這樣的確讓我對這些東西印象深刻哈哈哈
https://github.com/changtintin/Design-Pattern/tree/master/Ch2/Java
Disclaimer
因為讀的是原文版,所以難免會有翻譯詞不達意或是專有名詞上的差異,有錯誤的話歡迎在留言區一起交流!