讓物件保持訊息靈通
01需求
一個WeatherData物件負責追蹤目前的天氣狀況(溫度,濕度,氣壓),希望你們能建立一個應用,有三種布告板,分別顯示目前的狀況、氣象統計及簡單的預報,當WeatherObject物件獲得最新的測量資料時,三種布告板必須實時更新,而且,這是一個可以擴展的氣象站,Weather-O-Rama氣象站希望公布一組API,好讓其他開發人員可以寫出自己的氣象布告板,并插入此應用中,我們希望能提供這樣的API,
class WeatherData{
public int getTemperature(){
}
public int getHumidity(){
}
public int getPressure(){
}
public void measurementsChanged(){
//一旦氣象測量更新,此方法會被呼叫
}
}
實作1
public class WeatherData {
// 實體變數宣告
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
// 這里是其他WeatherData方法
}
缺點:
>針對實作編程
對于每個新的顯示,都得修改這份代碼
沒有辦法在運行時添加/移除顯示元素
沒有封裝改變的部分
02觀察者模式
觀察者模式:定義物件之間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知并自動更新;
有幾種不同的實作方法,大多數圍繞著包括主題和觀察者介面的類設計
類圖:

第四個設計原則:為了互動物件之間松耦合設計而努力,
>主題只知道觀察者實作了某個介面(也就是Observer介面)
任何時候我們都可以增加新的觀察者,也可以在任何時候洗掉某些觀察者,
有新型別的觀察者出現時,主題的代碼不需要修改,
獨立復用主題和觀察者
改變主題/觀察者其中一方,不會影響另一方
實作2
設計氣象站

實作氣象站
1.構建主題subject和觀察者observer介面
//主題介面
public interface Subject{
//注冊觀察者
public void registerObserver(Observer o);
//洗掉觀察者
public void removeObserver(Observer o);
//當主題狀態改變時,這個方法會被呼叫,以通知所有的觀察者
public void notifyObserver();
}
public interface Observer {
//當氣象觀測值改變時,主題會把這些狀態值當作方法的引數,傳送給觀察者
public void update(float temp,float humidity,float pressure);
}
public interface DisplayElement{
//當需要顯示時,呼叫此方法
public void display();
}
2.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>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);//一個觀察者注冊的時候,把它添加到list的末端
}
@Override
public void removeObserver(Observer o) {
int i=observers.indexOf(o);//獲得物件索引
if(i>=0){
observers.remove(i);
}
}
@Override
public void notifyObserver() {
for(Observer observer:observers){
observer.update(temperature,humidity,pressure);
}
}
//當從氣象站得到更新觀測值時,我們通知觀察者
public void measurementsChanged(){
notifyObserver();
}
//測驗資料
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged();
}
//WeatherData的其他方法
}
3.構造顯示元素
顯示類實作Observer介面,所以可以從WeatherData物件中獲取變化
public class CurrentConditionDisplay implements Observer,DisplayElement{
private float temperature;
private float humidity;
private Subject weatherData;
//構造器被傳入weatherData物件(Subject),用它來把 【顯示】 注冊為 【觀察者】
public CurrentConditionDisplay(WeatherData weatherData){
this.weatherData=https://www.cnblogs.com/yunshalee/p/weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("current conditions:" + temperature + "F degrees and " + humidity + "% humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature=temp;
this.humidity=humidity;
display();
}
}
4.啟動氣象站
public class WeatherStation {
public static void main(String[] args) {
//創建物件
WeatherData weatherData = https://www.cnblogs.com/yunshalee/p/new WeatherData();
//創建顯示
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
//模擬氣象測量
weatherData.setMeasurements(80,65,30.4f);
}
}
缺點:
>每次更新資訊都會全部通知到每個觀察者,而觀察者只想要有用的資訊;
不能擴展更多的顯示【因為觀察者介面的update方法是固定引數】
實作3(改進)
我們可以讓Observer按需要從Subject拉取,當Subiect的資料變化,我們馬上通過呼叫update()傳送資料,推送新的溫度、濕度和氣壓值給Observer,
為了切換到拉取方式,我們需要對已有代碼做一些小小的修改
Subject的發送通知.....
修改WeatherData中的notifyObservers()方法,不帶引數地呼叫Observer中的update()方法:
public void notifyobservers() {
for(Observer observer:observers){
observer.update();
}
}
Observer的接收通知....
修改Observer介面,改變update()方法的簽名,這樣它就沒有引數了:
public interface Observer {
public void update();
}
修改每個具體Observer,改變其各自的update0方法的簽名,并使用WeatherData的getter方法從Subject獲取氣象資料,CurrentConditionsDisplay類的新代碼如下:
public void update() {
this.temperature = weatherData.getTemperature();
this,humidity = weatherData.getHumidity();
display();
}
總結
OO基礎:抽象
OO原則:
>封裝變化,
組合優于繼承
針對介面編程,而不是針對實作,
盡力達到互動物件之間的松耦合設計,【新增】
OO模式:
觀察者模式:定義物件之間的一對多依賴這樣,當一個物件改變狀態時,它的所有依賴者會被通知并自動更新,
要點
觀察者模式定義物件之間的一對多關系,
主題使用通用介面更新觀察者,
任何具體型別的觀察者都可參與該模式,只要它們實作察者介面,
觀察者是松耦合的,除了知道它們實作觀察者介面之外,主題對它們的其他事情不知情
使用該模式時,你可以從主題推或拉資料(拉被認為更“正確”)
Swing大量使用觀察者模式許多GUI框架也是這樣,
你也會在其他很多地方發現該模式,包括RxJava、JavaBeans和RMI,以及其他語言的框架,像Cocoa、Swift和JavaScript事件,
觀察者模式和出版/訂閱模式相關,出版/訂閱模式用于更復雜得多主題和/或多訊息型別的情形,
觀察者模式是一個常用的模式,當我們學習模型-視圖-控制器時,還會看到它,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/549918.html
標籤:設計模式
上一篇:【解釋器設計模式詳解】C/Java/Go/JS/TS/Python不同語言實作
下一篇:01介紹(策略模式)
