Java設計模式知識學習-----觀察者模式
定義
出版社+訂閱者=觀察者模式,其中出版社改成為‘主題’,訂閱者改稱為‘觀察者’。觀察者模式定義了物件之間的一對多依賴關係,當一個物件改變狀態時,他的所有依賴者都會收到通知並且自動更新。這裡和訂閱報紙是一樣的道理,當出版社有了新報紙,那麼所有訂閱了該報紙的人都會收到新的報紙。
在這裡,發生改變的物件(出版社)稱為觀察目標(主題),被通知的物件(訂閱報紙的人)稱為觀察者,一個觀察目標可以對應多個觀察者,而這些觀察者之間沒有相互聯絡,所以可以根據需要增加和刪除觀察者,使得系統更易於擴充套件。
類圖
例項
需求
在氣象觀測站中,有三個佈告板,分別顯示目前狀況,氣象統計和天氣預報。WeatherData類中具有setter和getter方法,可以取得三個測量值,當有新的資料時,WeatherData類中的measurementsChanged()方法就會被呼叫,我們要做的就是,一旦WeatherData類有新資料,我們就要更新佈告板。
類圖設計
程式碼實現
Subject 主題介面
public interface Subject {
//觀察者註冊
public void registerObserver(Observer o);
//移除觀察者
public void removeObserver(Observer o);
//當主題狀態該變時,這個方法就會被呼叫,以通知所有的觀察者
public void notifyObserver();
}
Observer 觀察者介面
public interface Observer { //當氣象觀測值改變時,主題就會將這些狀態值當做方法的引數,傳送給觀察者 //所有的的觀察者都必須實現update方法,以實現觀察者介面 public void update(float temperature,float humidity,float pressure); }
DisplayElement 佈告板顯示介面
public interface DisplayElement {
//當佈告板需要顯示的,就會呼叫此方法
public void display();
}
WeatherData實現主題介面 WeatherData.java
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); } @Override public void removeObserver(Observer o) { int i = observers.indexOf(o); if(i >=0){ observers.remove(o); } } //這裡就是將狀態迴圈的通知給每一個觀察者,因為每一個觀察者都實現了update方法, @Override public void notifyObserver() { for(int i=0; i < observers.size();i++){ 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(); } }
CurrentConditionsDisplay 佈告板
/**
* 顯示目前狀況的佈告板:顯示溫度,溼度和氣壓
*@author lky
*@date 2018年1月16日
*/
public class CurrentConditionsDisplay implements Observer,DisplayElement {
private float temperature;// 溫度
private float humidity;// 溼度
private float pressure; // 氣壓
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("我是目前狀況佈告板,現在溫度是:"+temperature+
"℃"+"溼度是:"+humidity+"氣壓是:"+pressure);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
}
天氣預報佈告板
/**
* 天氣預報佈告板:顯示當前的天氣狀況
*@author lky
*@date 2018年1月16日
*/
public class ForecastDisplay implements Observer,DisplayElement{
private float currentPressure = 29.92f; //當前的氣壓
private float lastPressure; // 最後的氣壓
private WeatherData weatherData;
public ForecastDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature,float humidity,float pressure) {
lastPressure = currentPressure;// 將當前的氣壓賦給最後的氣壓
currentPressure = pressure;// 將更新的氣壓賦給當前氣壓
display();
}
public void display() {
if (currentPressure > lastPressure) {
System.out.println("我是天氣預報佈告板,現在是:氣壓升高,天氣轉好!");
} else if (currentPressure == lastPressure) {
System.out.println("我是天氣預報佈告板,現在是:氣壓不變,天氣維持!");
} else if (currentPressure < lastPressure) {
System.out.println("我是天氣預報佈告板,現在是:氣壓降低,天氣變壞!");
}
}
}
天氣統計佈告板
/**
* 天氣統計佈告板:顯示最高溫度,最低溫度和平均溫度
*@author lky
*@date 2018年1月16日
*/
public class StatisticsDisplay implements Observer,DisplayElement{
private float maxTemp = 0.0f;
private float minTemp = 200;
private float tempSum= 0.0f;
private int numReadings;
private WeatherData weatherData;
public StatisticsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity, float pressure) {
tempSum += temperature;
numReadings++;
if (temperature > maxTemp) {
maxTemp = temperature;
}
if (temperature < minTemp) {
minTemp = temperature;
}
display();
}
public void display() {
System.out.println("我是天氣統計佈告板,平均溫度是: " + (tempSum / numReadings)
+ ",最高溫度是:" + maxTemp + ",最低溫度是:" + minTemp);
}
}
酷熱指數佈告板
/**
* 酷熱指數佈告板,根據溫度和溼度採用特定的公式映象計算的。
*@author lky
*@date 2018年1月16日
*/
public class HeatIndexDisplay implements Observer,DisplayElement {
float heatIndex = 0.0f;
private WeatherData weatherData;
public HeatIndexDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature,float humidity,float pressure) {
heatIndex = computeHeatIndex(temperature, humidity);
display();
}
//在佈告板中自定義方法。
private float computeHeatIndex(float t, float rh) {
float index = (float)((16.923 + (0.185212 * t) + (5.37941 * rh) - (0.100254 * t * rh)
+ (0.00941695 * (t * t)) + (0.00728898 * (rh * rh))
+ (0.000345372 * (t * t * rh)) - (0.000814971 * (t * rh * rh)) +
(0.0000102102 * (t * t * rh * rh)) - (0.000038646 * (t * t * t)) + (0.0000291583 *
(rh * rh * rh)) + (0.00000142721 * (t * t * t * rh)) +
(0.000000197483 * (t * rh * rh * rh)) - (0.0000000218429 * (t * t * t * rh * rh)) +
0.000000000843296 * (t * t * rh * rh * rh)) -
(0.0000000000481975 * (t * t * t * rh * rh * rh)));
return index;
}
public void display() {
System.out.println("我是酷熱指數佈告板,現在的酷熱指數為: " + heatIndex);
}
}
測試
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay conditionsDisplay = new CurrentConditionsDisplay(weatherData);
StatisticsDisplay observer2 = new StatisticsDisplay(weatherData);
ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
System.out.println("===================================");
weatherData.setMeasurements(70, 55, 20.4f);
System.out.println("===================================");
weatherData.setMeasurements(90, 75, 40.4f);
}
}
結果
我是目前狀況佈告板,現在溫度是:80.0℃溼度是:65.0氣壓是:30.4
我是天氣統計佈告板,平均溫度是: 80.0,最高溫度是:80.0,最低溫度是:80.0
我是天氣預報佈告板,現在是:氣壓升高,天氣轉好!
我是酷熱指數佈告板,現在的酷熱指數為: 82.95535
===================================
我是目前狀況佈告板,現在溫度是:70.0℃溼度是:55.0氣壓是:20.4
我是天氣統計佈告板,平均溫度是: 75.0,最高溫度是:80.0,最低溫度是:70.0
我是天氣預報佈告板,現在是:氣壓降低,天氣變壞!
我是酷熱指數佈告板,現在的酷熱指數為: 75.9113
===================================
我是目前狀況佈告板,現在溫度是:90.0℃溼度是:75.0氣壓是:40.4
我是天氣統計佈告板,平均溫度是: 80.0,最高溫度是:90.0,最低溫度是:70.0
我是天氣預報佈告板,現在是:氣壓升高,天氣轉好!
我是酷熱指數佈告板,現在的酷熱指數為: 108.19608
執行流程分析
- 例項化一個主題物件(WeatherData)
- 例項化一個現實目前狀況的佈告板,並傳入主題物件。
- 在目前狀況的佈告板的建構函式中,將當前佈告板註冊為傳入的主題的觀察者
- 同理,將天氣統計佈告板,天氣預報佈告板,酷熱指數佈告板都註冊為WeatherData的觀察者
- 呼叫主題物件的setMeasurements方法,模擬主題物件的值發生改變。
- 第一次傳入不同的溫度,溼度和氣壓。主題物件呼叫measurementsChanged()方法。
- measurementsChanged()方法中呼叫notifyObserver()方法。
- notifyObserver()方法中迴圈呼叫observer的update()方法,呼叫的是介面方法,具體執行的是每一個例項型別的update()方法,
- 每一個佈告板例項的update()方法,是具體的資料準備,然後呼叫display()方法,顯示佈告板資訊。
整體分析圖
總結
- 觀察者模式定義了物件之間的一對多關係,多個觀察者監聽同一個主題(被觀察者),當主題的狀態發生改變時,會通知所有的觀察者。
- 觀察者模式中具體主題是主題的子類,通常包含經常發生改變的資料,當他的狀態發生改變時,會通知所有他的觀察者物件,主題用一個共同的介面來更新觀察者。
- 觀察者實現的是同一個介面,也就是主題發生改變時通知的介面,不同的觀察者具體的實現方法不一樣。
- 觀察者與被觀察者之間用鬆耦合的方式結合。
相關推薦
Java設計模式知識學習-----觀察者模式
定義 出版社+訂閱者=觀察者模式,其中出版社改成為‘主題’,訂閱者改稱為‘觀察者’。觀察者模式定義了物件之間的一對多依賴關係,當一個物件改變狀態時,他的所有依賴者都會收到通知並且自動更新。這裡和訂閱報紙是一樣的道理,當出版社有了新報紙,那麼所有訂閱了該報紙的人
Java設計模式11:觀察者模式
一、什麼是觀察者模式 在閻巨集博士的《JAVA與模式》一書中開頭是這樣描述觀察者(Observer)模式的: 觀察者模式是物件的行為模式,又叫釋出-訂閱(Publish/Subscribe)模式、模型-檢視(Model/View)模式、源-監聽器(Source/Listener)模式
設計模式學習——觀察者模式
觀察者模式 定義:定義物件間一種一對多的依賴關係,使得每當一個物件發生變化時,則所有依賴於他的物件都會得到通知並自動更新。 使用場景 關聯行為場景 事件多級觸發場景 跨系統的訊息交換場景,如訊息佇列、事件匯流排的處理機制 特點:實現物件的解耦,將觀察
Java設計模式之《觀察者模式》及應用場景
觀察者模式,又可以稱之為釋出-訂閱模式,觀察者,顧名思義,就是一個監聽者,類似監聽器的存在,一旦被觀察/監聽的目標發生的情況,就會被監聽者發現,這麼想來目標發生情況到觀察者知道情況,其實是由目標獎情況傳送到觀察者的。 觀察者模式多用於實現訂閱功
Java設計模式六:觀察者模式(Observer)
觀察者模式定義了物件間的一種一對多依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並被自動更新。 它將觀察者和被觀察者的物件分離開。提高了應用程式的可維護性和重用性。 實現觀察者模式有很多形式,一種是“註冊---通知---撤銷註冊”的形式。 觀察者Observer:所有潛在的觀察
Java描述設計模式(11):觀察者模式
本文原始碼:GitHub·點這裡 || GitEE·點這裡 一、觀察者模式 1、概念描述 觀察者模式是物件的行為模式,又叫釋出
重學 Java 設計模式:實戰觀察者模式「模擬類似小客車指標搖號過程,監聽訊息通知使用者中籤場景」
![](https://img-blog.csdnimg.cn/20200630231649444.png) 作者:小傅哥 部落格:[https://bugstack.cn](https://bugstack.cn) - `原創系列專題文章` >沉澱、分享、成長,讓自己和他人都能有所收穫!
設計思想與模式之五觀察者模式
per -- 什麽 over out junit 測試類 rem second 一 概述 1.什麽是觀察者模式? 將一個對象視作被觀察者,當它發出某種行為或者發生某種變化時,通知所有依賴它的對象(觀察者),這種設計模式叫做觀察者設計模式。 2.觀察者設
設計模式筆記8: 觀察者模式
image 子類 http view 完全 log 註冊 功能 技術分享 1.1 定義 定義了一種一對多的依賴關系,讓多個觀察者同時監聽一個對象,但這個對象發生變化時,會通知所有觀察者對象,使他們能夠更新自己。 1.2 類圖 1.3 代碼 Vi
Android 設計模式情景分析——觀察者模式
get ble not exception 知識庫 system observe 行為型模式 .get 觀察者模式是一種使用頻率非常高的模式,有時也被稱作發布/訂閱模式,屬於行為型模式,它最常用的是 GUI 系統、訂閱——發布系統,它一個重要作用就是解耦,使得它們之間的依賴
淺談java中內置的觀察者模式與動態代理的實現
所有 代理 notify play ani effect 一個 indicate protected 一.關於觀察者模式 1.將觀察者與被觀察者分離開來,當被觀察者發生變化時,將通知所有觀察者,觀察者會根據這些變化做出對應的處理。 2.jdk裏已經提供對應的Observer
【設計模式】 模式PK:觀察者模式VS責任鏈模式
ipa 隨機 保留 聲明 pri 測試 void c_str window 1、概述 為什麽要把觀察者模式和責任鏈模式放在一起對比呢?看起來這兩個模式沒有太多的相似性,真沒有嗎?回答是有。我們在觀察者模式中也提到了觸發鏈(也叫做觀察者鏈)的問題,一個具體的角色既可以是觀察者
設計模式(19)--Observer(觀察者模式)--行為型
直接 pen 創建 方法調用 設計方案 之間 分離 number 運行期 作者QQ:1095737364 QQ群:123300273 歡迎加入! 1.模式定義: 觀察者模式是對象的行為模式,又叫發布-訂閱(Publish/Subscribe)模式、模
【編程思想】【設計模式】【行為模式Behavioral】觀察者模式Observer
setting notify tput pes env observer 設計模式 mod pre Python轉載版 https://github.com/faif/python-patterns/blob/master/behavioral/observer.py
【Python設計模式】06 觀察者模式-瞭解物件的情況
六、觀察者模式-瞭解物件的情況 這章可以討論行為型設計模式:觀察者設計模式 本章主題 行為型設計模式簡介 觀察者設計模式及其 UML圖 利用 Python3.x程式碼實現一個真實用例 鬆耦合的強大威力 常見問答 1. 行為型模式簡介
vue原始碼學習——觀察者模式
情景:接觸過vue的同學都知道,我們曾經都很好奇為什麼vue能這麼方便的進行資料處理,當一個物件的某個狀態改變之後,只要依賴這個資料顯示的部分也會發生改變,如果你依舊很好奇,那麼今天你就可以瞭解一下實現的原理 什麼是觀察者模式 官方解釋是
設計模式(十六) 觀察者模式
觀察者模式也叫釋出/訂閱模式, 定義一種1對多的依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並被自動更新 觀察者模式的幾個角色: Subject 被觀察者。定義被觀察者必須實現的職責,它必須能夠動態的增加,取消觀察者。 要有管理觀察者並通知觀
設計模式 ( 十五 ) 觀察者模式Observer(物件行為型)
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
設計模式——行為型——觀察者模式
在閻巨集博士的《JAVA與模式》一書中開頭是這樣描述觀察者(Observer)模式的: 觀察者模式是物件的行為模式,又叫釋出-訂閱(Publish/Subscribe)模式、模型-檢視(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents
設計模式(DesignPattern)之觀察者模式(Observable)
1、定義 觀察者模式的重要作用就是解耦,定義物件之間一對多的依賴關係,被依賴物件為Subject,依賴物件為Observer,Subject通知Observer更新狀態。 2、使用場景 跨系統的訊息交換,如訊息佇列,事件匯流排的處理機制。 事件多級觸發。 關聯的