在許多場景,是需要建立一對多,訊息及時且弱耦合,設計模式面向介面,推出觀察者模式,
場景:氣象資料發送給三個資訊版,分別為當前資料,氣象統計值,天氣預報,一旦氣象資料更新,三個資訊版就要封信面板資訊展示,
請查看為不使用觀察者模式的代碼:
/** * 利用weather 資料更新3個資訊版,當前資料,氣象統計值,天氣預報 */ public class weather { private float temperature;//溫度 private float humidity;//濕度 private float pressure;//氣壓 public float getTemperature() { return temperature; } public weather(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; } 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; } public void paramChanged(){ float temp = getTemperature(); float hum = getHumidity(); float pressure = getPressure(); currentCondutionDisplay.update(temp,hum,pressure); //如果要添加洗掉資訊板就要在weather類洗掉添加,造成強耦合 } }
class currentCondutionDisplay { private float temperature;//溫度 private float humidity;//濕度 private float pressure;//氣壓 public currentCondutionDisplay(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; } protected static void update(float temperature, float humidity, float pressure){ display(temperature,humidity,pressure); } private static void display(float temperature, float humidity, float pressure){ System.out.println("當前天氣 溫度 "+temperature + "濕度"+humidity+"氣壓 "+pressure); } }
public class testmain { public static void main(String[] args) { weather weatherdata = new weather(38,60,1000); weatherdata.paramChanged(); } }
弊端:假設需要添加洗掉資訊版,就需要在weather類修改,造成類之間的強耦合,
對此,引入設計模式中的觀察者模式
觀察者模式
觀察者模式含義:當物件間存在一對多關系時,則使用觀察者模式(Observer Pattern),比如,當一個物件被修改時,則會自動通知依賴它的物件,觀察者模式屬于行為型模式,
觀察者模式目的:解決強耦合問題,
干說定義枯燥,舉個場景:郵局發送示例
小明(即你自己)向郵局發送信件,郵局我們可以當成主體(subject)被觀察者,小明想要通過郵局發送信件給三個人,分別為女朋友小紅,小明父母,小明朋友小張,這三個人我們可以定義為觀察者(observer),我們將三位收信人,寫成一個收信串列,即觀察者串列,注冊給郵局,郵局一旦接受到小明信件,就會更新自己的狀態,通知三位收信人,即觀察者們,而收信人們(觀察者們)收到信件會更新自己的狀態,有不同的動作,小紅會寄一份帶有一片玫瑰花瓣的信件給小明,小明父母會寄土特產給小明,小張則在收到信件直接打電話給小明,但也有突發狀況,比如小紅生氣,拒收小明信件,那么郵局就暫時把收信人串列移除小紅,再比如小明想給小紅好朋友小紫寫信讓她跟小紅說說好話,那么就加小紫到收信人串列,
觀察者模式類似于這樣,只不過收信人定義為觀察者,實作觀察者介面,郵局則定義為被觀察者,實作主體介面,郵局和觀察者們形成一對多的關系,郵局可以洗掉添加觀察者,推送更新狀態給觀察者,
在氣象局此例中,氣象資料weather類為主體,實作subject介面,具有移除添加資訊版和改變引數通知資訊版,三個資訊版為觀察者,氣象資料更新則update自己的狀態,觀察者和主體有一個注冊的關系建立連接,具體實作可以觀察下面流程圖

如圖,三個面板除了實作obsever介面還實作display介面,具有介面的update()和display()方法,只不過三個資訊版可以重寫這兩個方法,
代碼實作:
public interface DisplayElement { public void display(); } public interface Observer { public void update(float temp,float humidity,float pressure); } public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
public class currentConditionsDisplay implements Observer, DisplayElement { //實作了observer介面,可從weather獲得改變 private float temperature; private float humidity; private Subject weather; public currentConditionsDisplay(Subject weather) {//注冊,聯系subject this.weather = weather; weather.registerObserver(this); } @Override public void display() { System.out.println("Current conditions: "+ temperature +" degrees and "+ humidity+ " %humidity"); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity;//將溫度濕度保存起來,呼叫display display(); } }
public class forecastDisplay implements Observer, DisplayElement { //實作了observer介面,可從weather獲得改變 private float temperature; private float humidity; private Subject weatherData; private String status; public forecastDisplay(Subject weatherData) {//注冊,聯系subject this.weatherData =https://www.cnblogs.com/first-hand/p/ weatherData; weatherData.registerObserver(this); } @Override public void display() { if (this.temperature>37){ this.status = "too hot"; } if(this.temperature<38 & this.temperature>20 & this.humidity>45){ this.status = "warm"; }if(this.temperature<=10){ this.status = "too cold"; } System.out.println("today weather: "+ this.status); } @Override public void update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity;//將溫度濕度保存起來,呼叫display display(); } }
測驗代碼:
public class weatherStation { public static void main(String[] args) { weather weather = new weather(); currentConditionsDisplay currentConditionsDisplay = new currentConditionsDisplay(weather); forecastDisplay forecast = new forecastDisplay(weather); weather.setParams(10,20,1000); weather.setParams(25,60,1000); weather.setParams(39,60,1000); } }
實作效果:

觀察者模式優缺點:
優點: 1、觀察者和被觀察者是抽象耦合的, 2、建立一套觸發機制,
缺點: 1、如果一個被觀察者物件有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間, 2、如果在觀察者和觀察目標之間有回圈依賴的話,觀察目標會觸發它們之間進行回圈呼叫,可能導致系統崩潰, 3、觀察者模式沒有相應的機制讓觀察者知道所觀察的目標物件是怎么發生變化的,而僅僅只是知道觀察目標發生了變化,
代碼:https://github.com/akadiaego/designPatterns
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/423337.html
標籤:設計模式
