觀察者模式(Observer Pattern)
是什麼?
怎麼用?
什麼情況下用?
例項!
觀察者模式:
一個目標物件管理所有依賴於它的觀察者物件,並且當它本身的狀態改變時主動發出通知。
這時候就有問題了,目標怎麼知道誰是觀察者?誰不是觀察者?而且目標要怎麼通知觀察者?
(個人感覺兩個類通訊就能用到這東西)
使用場景:
今日頭條文章釋出後需要一系列的後續處理流程,比如更新這個作者建立的文章總數、將這篇文章推薦到對應的頻道、劃分文章的欄目、上報到推薦系統等等。那要其他的這些要怎麼知道文章是否釋出呢?這時候就可以用到觀察者模式了(事件機制)!
原理:
目標類需要:
1、註冊觀察者(觀察者通知目標:我要當你的觀察者)
2、移除觀察者(觀察者通知目標:我要溜了)
3、呼叫觀察者的提供的方法通知觀察者
觀察者需要:
1、提供目標通知觀察者時用到的方法
2、在建構函式中呼叫目標的註冊方法將自己註冊成目標的觀察者
例子:
氣象檢測例子:
如圖,氣象站是獲取實際氣象資料的物理裝置,WeatherData物件是用來追蹤氣象站的資料,並更新佈告板。
擴充WeatherData物件,使得佈告板能夠及時更新,並利於以後的擴充套件。
Subject 是抽象目標,所有的目標都繼承這個抽象類,這個抽象類提供了三個最基本的註冊、移除、通知觀察者的方法!
WeatherData 是具體目標,繼承自抽象目標Subject,這個類的notifyObserver通過呼叫觀察者的udpate方法通知觀察者狀態變化!
Observer 是抽象觀察者,所有的觀察者都繼承這個抽象類,這個抽象類提供了udpate方法,以便目標呼叫。
CurrentConditionDisplay、StatisticsDisplay 是具體觀察者,在這兩個類的構造方法中實現了「註冊為目標的觀察者」!
<Head First 設計模式> code:
package Observer; public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObserver(); }Subject
package Observer; import java.util.ArrayList; public class WeatherData implements Subject{ private ArrayList observers; private float temperature; private float humidity; private float pressure; public WeatherData() { observers = new ArrayList(); } 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 notifyObserver() { for (int i =0; i< observers.size(); i++) { Observer observer = (Observer)observers.get(i); 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
package Observer; public interface Observer { public void update(float temp, float humidity, float pressure); }Observer
package Observer; public class CurrentConditionsDisplay implements Observer { private float temperature; private float humidity; private float pressure; private Subject weatherDay; public CurrentConditionsDisplay(Subject subject) { this.weatherDay = subject; weatherDay.registerObserver(this); } public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; display(); } public void display() { System.out.println("temp = " + temperature + " humi = " + humidity + " press = " + pressure); } }CurrentConditionsDisplay
package com.company; import Observer.CurrentConditionsDisplay; import Observer.WeatherData; public class Main { public static void main(String[] args) { WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); weatherData.setMeasurements(1, 3, 4); } }Main
結果:
temp = 1.0 humi = 3.0 press = 4.0