1. 程式人生 > 實用技巧 >設計模式之十六之觀察者模式

設計模式之十六之觀察者模式

觀察者模式介紹

 觀察者模式類似訂牛奶業務

1) 奶站/氣象局:Subject

2) 使用者/第三方網站:Observer

 Subject:登記註冊、移除和通知

1) registerObserver 註冊

2) removeObserver 移除

3) notifyObservers() 通知所有的註冊的使用者,根據不同需求,可以是更新資料,讓用 戶來取,也可能是實施推送,看具體需求定

 Observer:接收輸入

 觀察者模式:物件之間多對一依賴的一種設計方案,被依賴的物件為Subject, 依賴的物件為Observer,Subject通知Observer變化,比如這裡的奶站是 Subject,是1的一方。使用者時Observer,是多的一方。

案例:

天氣預報平臺案例

天氣預報專案需求,具體要求如下:

1) 氣象站可以將每天測量到的溫度,溼度,氣壓等等以公告的形式釋出出去(比如 釋出到自己的網站或第三方)。

2) 需要設計開放型API,便於其他第三方也能接入氣象站獲取資料。

3) 提供溫度、氣壓和溼度的介面 4) 測量資料更新時,要能實時的通知給第三方

uml類圖

程式碼實現:

package com.hy.observer.improve;

//介面, 讓WeatherData 來實現
public interface Subject {

    public void registerObserver(Observer o);
    
public void removeObserver(Observer o); public void notifyObservers(); } package com.hy.observer.improve; //觀察者介面,有觀察者來實現 public interface Observer { public void update(float temperature, float pressure, float humidity); } package com.hy.observer.improve; import java.util.ArrayList; /** * 類是核心 * 1. 包含最新的天氣情況資訊 * 2. 含有 觀察者集合,使用ArrayList管理 * 3. 當資料有更新時,就主動的呼叫 ArrayList, 通知所有的(接入方)就看到最新的資訊 *
@author Administrator * */ public class WeatherData implements Subject { private float temperatrue; private float pressure; private float humidity; //觀察者集合 private ArrayList<Observer> observers; //加入新的第三方 public WeatherData() { observers = new ArrayList<Observer>(); } public float getTemperature() { return temperatrue; } public float getPressure() { return pressure; } public float getHumidity() { return humidity; } public void dataChange() { //呼叫 接入方的 update notifyObservers(); } //當資料有更新時,就呼叫 setData public void setData(float temperature, float pressure, float humidity) { this.temperatrue = temperature; this.pressure = pressure; this.humidity = humidity; //呼叫dataChange, 將最新的資訊 推送給 接入方 currentConditions dataChange(); } //註冊一個觀察者 @Override public void registerObserver(Observer o) { // TODO Auto-generated method stub observers.add(o); } //移除一個觀察者 @Override public void removeObserver(Observer o) { // TODO Auto-generated method stub if(observers.contains(o)) { observers.remove(o); } } //遍歷所有的觀察者,並通知 @Override public void notifyObservers() { // TODO Auto-generated method stub for(int i = 0; i < observers.size(); i++) { observers.get(i).update(this.temperatrue, this.pressure, this.humidity); } } } package com.hy.observer.improve; public class CurrentConditions implements Observer { // 溫度,氣壓,溼度 private float temperature; private float pressure; private float humidity; // 更新 天氣情況,是由 WeatherData 來呼叫,我使用推送模式 @Override public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } // 顯示 public void display() { System.out.println("***Today mTemperature: " + temperature + "***"); System.out.println("***Today mPressure: " + pressure + "***"); System.out.println("***Today mHumidity: " + humidity + "***"); } } package com.hy.observer.improve; public class BaiduSite implements Observer { // 溫度,氣壓,溼度 private float temperature; private float pressure; private float humidity; // 更新 天氣情況,是由 WeatherData 來呼叫,我使用推送模式 @Override public void update(float temperature, float pressure, float humidity) { this.temperature = temperature; this.pressure = pressure; this.humidity = humidity; display(); } // 顯示 public void display() { System.out.println("===百度網站===="); System.out.println("***百度網站 氣溫 : " + temperature + "***"); System.out.println("***百度網站 氣壓: " + pressure + "***"); System.out.println("***百度網站 溼度: " + humidity + "***"); } } package com.hy.observer.improve; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //建立一個WeatherData WeatherData weatherData = new WeatherData(); //建立觀察者 CurrentConditions currentConditions = new CurrentConditions(); BaiduSite baiduSite = new BaiduSite(); //註冊到weatherData weatherData.registerObserver(currentConditions); weatherData.registerObserver(baiduSite); //測試 System.out.println("通知各個註冊的觀察者, 看看資訊"); weatherData.setData(10f, 100f, 30.3f); weatherData.removeObserver(currentConditions); //測試 System.out.println(); System.out.println("通知各個註冊的觀察者, 看看資訊"); weatherData.setData(10f, 100f, 30.3f); } }

執行結果: