成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 設計模式之觀察者模式

jsummer / 1340人閱讀

摘要:三內(nèi)置觀察者模式了解內(nèi)置觀察者模式包內(nèi)包含最基本的類與接口,這和上面的接口與接口很類似。根據(jù)具體的需求,如果內(nèi)置的觀察者模式不能滿設計,那么我們可以像剛開始那樣自己實現(xiàn)一套觀察者模式。參考資料設計模式

一、了解觀察者模式

1.1 什么是觀察者模式

觀察者模式定義了對象之間的一對多依賴,這樣一來,當一個對象狀態(tài)改變時,它的所有依賴者都會收到通知并自動更新。

典型的問題比如報社,只要你是他們的訂戶,他們每次有新報紙出版時,就會向你這送來,當你不想要看報紙時,取消訂閱,他們就不會再給你送報紙。

1.2 觀察者模式組成結構

抽象主題 (Subject):抽象主題角色把所有觀察者對象保存在一個集合里,每個主題都可以有任意數(shù)量的觀察者,抽象主題提供一個接口,可以增加和刪除觀察者對象。

具體主題 (ConcreteSubject):該角色將有關狀態(tài)存入具體觀察者對象,在具體主題的內(nèi)部狀態(tài)發(fā)生改變時,給所有注冊過的觀察者發(fā)送通知。

抽象觀察者 (Observer):是觀察者的抽象類,它定義了一個更新接口,使得在得到主題更改通知時更新自己。

具體觀察者 (ConcrereObserver):實現(xiàn)抽象觀察者定義的更新接口,以便在得到主題更改通知時更新自身的狀態(tài)。

1.3 觀察者模式 UML 圖解

二、觀察者模式具體應用

2.1 問題描述

氣象觀測站系統(tǒng):該系統(tǒng)中包含三部分,分別是氣象站 (獲取實際氣象數(shù)據(jù)的物理裝置)、WeatherData 對象 (追蹤氣象站的數(shù)據(jù),并更新布告板) 和布告板 (顯示天氣狀況給用戶看,布告板共有兩個,分別顯示當前的溫度以及對天氣進行預告)。

2.2 問題分析

我們想要使用觀察者模式去解決這個問題,首先要分析出什么是主題,什么是觀察者,問題的關鍵是找出一對多依賴關系。這里 WeatherData 類正如所說的“一”,而“多”是用于顯示天氣情況的布告板。

WeatherData 是有狀態(tài)的對象,它包括了溫度、濕度和氣壓,而這些值都會變化,當這些值改變時,必須通知布告板,好讓它們顯示最新的數(shù)據(jù)。所以把 WeatherData 類作為主題,布告板作為觀察者。

2.3 問題分析設計圖

2.4 代碼實現(xiàn)

PS:代碼模塊較多,建議將這些代碼拷下來運行一遍。

抽象主題接口 Subject

package com.jas.observer;

public interface Subject {

    /**
     *  注冊觀察者
     *  
     * @param observer 觀察者對象
     */
    void registObserver(Observer observer);

    /**
     *  移除觀察者
     *
     * @param observer 觀察者對象
     */
    void removeObserver(Observer observer);

    /**
     * 當主題狀態(tài)改變時,這個方法會被調(diào)用,通知所有的觀察者
     */
    void notifyObservers();
}

抽象觀察者接口 Observer

package com.jas.observer;

public interface Observer {

    /**
     * 當氣象觀測值改變時,主題會把這些狀態(tài)值作為參數(shù),傳送給觀察者
     * 
     * @param temp 溫度
     * @param humidity  濕度
     * @param pressure  壓力
     */
    void update(float temp, float humidity, float pressure);
}

布告信息接口 DisplayElement

package com.jas.observer;

public interface DisplayElement {
    void display();
}

具體主題類 WeatherData

package com.jas.observer;

import java.util.ArrayList;
import java.util.List;

public class WeatherData implements Subject {
    private float temperature;
    private float humidity;
    private float pressure;
    private List list = new ArrayList();    //使用集合保存所有的觀察者對象
    
    
    @Override
    public void registObserver(Observer observer) {
        list.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        int i = list.indexOf(observer);
        if(i >= 0 && i < list.size()){
            list.remove(i);
        }
    }

    @Override
    public void notifyObservers() {
        for (int i = 0; i < list.size(); i++) {    //遍歷集合中所有觀察者對象
            Observer observer = list.get(i);
            observer.update(temperature,humidity,pressure);    //調(diào)用觀察者的 update() 方法
        }
    }

    /**
     * 當氣象站的數(shù)據(jù)得到更新后,通知觀察者,調(diào)用 notifyObservers() 方法
     */
    public void measurementsChanged(){
        notifyObservers();
    }

    /**
     * 當氣象站數(shù)據(jù)改變后,設置新的數(shù)據(jù)值,并調(diào)用 measurementsChanged() 方法
     * 
     * @param temperature  溫度
     * @param humidity  濕度
     * @param pressure  氣壓
     */
    public void setMeasurements(float temperature, float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}

具體觀察者對象,當前天氣信息類 CurrentConditionsDisplay

package com.jas.observer;

public class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherData;

    /**
     * 通過構造函數(shù)將當前觀察者注冊給具體主題對象
     * 
     * @param weatherData 主題對象
     */
    public CurrentConditionsDisplay(Subject weatherData){
        this.weatherData = weatherData;
        weatherData.registObserver(this);
    }
    
    /**
     * 布告板信息展示
     */
    @Override
    public void display() {
        System.out.println("Current conditions list : " + "溫度 = " + 
                temperature + ", 濕度 = " + humidity + ", 氣壓 = " + pressure);
    }

    /**
     * 更新信息
     * 
     * @param temp 溫度
     * @param humidity  濕度
     * @param pressure  壓力
     */
    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        display();
    }
}

具體觀察者對象,預測天氣信息類 ForecastDisplay(簡單將數(shù)據(jù)減一)

package com.jas.observer;

public class ForecastDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherData;

    /**
     * 通過構造函數(shù)將當前觀察者注冊給主題對象
     *
     * @param weatherData 主題對象
     */
    public ForecastDisplay(WeatherData weatherData){
        this.weatherData = weatherData;
        weatherData.registObserver(this);
    }
    
    @Override
    public void display() {
        System.out.println("Forecast conditions list : " + "溫度 = " +
                (temperature - 1.0) + ", 濕度 = " + (humidity - 1.0) + ", 氣壓 = " + (pressure - 1.0));
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        display();
    }
}

氣象站類 WeatherStation

package com.jas.observer;

public class WeatherStation {
    public static void main(String[] args) {
        
        WeatherData weatherData = new WeatherData();
        
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
        
        //當具體主題對象數(shù)據(jù)發(fā)生變化,所有依賴者 (觀察者) 都會實現(xiàn)自動數(shù)據(jù)更新
        weatherData.setMeasurements(18,65,30);
    }
}

    /**
     * 輸出
     * Current conditions list : 溫度 = 18.0, 濕度 = 65.0, 氣壓 = 30.0
     * Forecast conditions list : 溫度 = 17.0, 濕度 = 64.0, 氣壓 = 29.0
     */

2.5 自定義觀察者模式總結

觀察者模式可以輕松實現(xiàn)松耦合,因為主題并不需要知道觀察者的具體類是誰,做了些什么,并且我們可以在任何時候新增觀察者。由于一個主題可能對應多個觀察者,所以當某一個觀察者出現(xiàn)問題時,可能導致其他的觀察者也不能正常工作。因此在一定程度上,存在著效率問題。

三、Java 內(nèi)置觀察者模式

3.1 了解 Java 內(nèi)置觀察者模式

java.util 包內(nèi)包含最基本的Observable 類Observer 接口,這和上面的 Subject 接口與 Observer 接口很類似。Observable 類與 Observer 接口使用起來更方便,因為許多的功能已經(jīng)提供了。

3.2 Java 內(nèi)置觀察者模式如何運作

(1)如何把對象定義為觀察者?

實現(xiàn)觀察者 (Observer) 接口,調(diào)用任何 Observable 對象的 addObserve() 方法。當不想要當觀察者時,調(diào)用 deleteObserve() 方法。

(2)可觀察者如何發(fā)送通知?

先調(diào)用 setChanged() 方法,標記狀態(tài)已經(jīng)被改變的事實。

調(diào)用 notifyObservers()notifyObservers(Object arg) 方法。

(3)觀察者如何接收通知?

同以前一樣,觀察者實現(xiàn)了 update(Observable o, Object arg) 方法,只是方法簽名不太一樣。

3.3 重寫氣象觀測站系統(tǒng)

主題類 WeatherData

package com.jas.jdk.observer;

import java.util.Observable;

public class WeatherData extends Observable {
    private float temperature;
    private float humidity;
    private float pressure;
    
    public void measurementsChanged(){
        //在通知所有觀察者之前,先調(diào)用 setChanged() 方法,用來表示狀態(tài)已經(jīng)改變
        setChanged();
        notifyObservers();
    }
    
    public void setMeasurements(float temperature, float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
    
    public float getTemperature(){
        return temperature;
    }
    
    public float getHumidity(){
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}

具體觀察者對象,當前天氣信息類 CurrentConditionsDisplay

package com.jas.jdk.observer;

import java.util.Observable;
import java.util.Observer;

public class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private float pressure;
    private Observable observable;

    /**
     * 通過構造函數(shù),將當前對象記錄為觀察者
     * 
     * @param observable 主題對象
     */
    public CurrentConditionsDisplay(Observable observable){
        this.observable = observable;
        observable.addObserver(this);
    }
    
    @Override
    public void display() {
        System.out.println("Current conditions list : " + "溫度 = " +
                temperature + ", 濕度 = " + humidity + ", 氣壓 = " + pressure);
    }

    @Override
    public void update(Observable o, Object arg) {
        if(o instanceof WeatherData){
            WeatherData weatherData = (WeatherData) o;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            this.pressure = weatherData.getPressure();
            display();
        }
    }
}

氣象站類 WeatherStation(同上)

package com.jas.jdk.observer;


public class WeatherStation {
    public static void main(String[] args) {
        
        WeatherData weatherData = new WeatherData();
        
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
        //ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
        
        weatherData.setMeasurements(80,65,30.4f);
    }
}

     /**
     * 輸出
     * Current conditions list : 溫度 = 80.0, 濕度 = 65.0, 氣壓 = 30.4
     */

3.4 Java 內(nèi)置觀察者模式總結

Java 內(nèi)置的觀察者模式允許觀察者有選擇的獲取數(shù)據(jù),而不是主題對象強制將更新數(shù)據(jù)全部推送個每個觀察者。

Observable 是一個類,并不是一個接口,這意味著你繼承它的同時,不能再繼承其他的類。在 Observable 類中 setChanged() 方法被保護了起來 (protected),除非你繼承該類,否則你無法創(chuàng)建 Observable 實例組合到你自己的對象中來。所以它違反了一個原則:“多用組合,少用繼承”。

還有一點需要要注意的是:內(nèi)置的觀察者模式,觀察者被通知的順序并不是唯一的 (上面只定義了一個觀察者),有時候并不能達到我們一開始的目的,你可以定義多個觀察者驗證一下。

根據(jù)具體的需求,如果 Java 內(nèi)置的觀察者模式 API 不能滿設計,那么我們可以像剛開始那樣自己實現(xiàn)一套觀察者模式。

參考資料

《Head First 設計模式》

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/77238.html

相關文章

  • Java設計模式察者模式

    摘要:觀察者模式的使用場景比如你微博關注了一個人,那么這個人發(fā)布的微博就會推送到你這。 Java設計模式之觀察者模式 一直想寫一篇學習觀察者模式的總結沒有契機,今天學習阻塞隊列的原理時候看到在實現(xiàn)生產(chǎn)者消費者的時候用到了通知模式,就是所謂的觀察者模式,正好順便整理一下。 1. 簡介 觀察者模式定義對象間的一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更...

    haitiancoder 評論0 收藏0
  • 前端學習筆記察者模式

    摘要:觀察者模式也稱發(fā)布訂閱模式它的作用就是當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知,自動刷新對象狀態(tài)舉個生活比較常見常見的例子比如你去面試之后,面試官看你表現(xiàn)不錯,最后會跟你要聯(lián)系方式,以便之后可以聯(lián)系你。 觀察者模式也稱發(fā)布-訂閱模式,它的作用就是當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知,自動刷新對象狀態(tài) 舉個生活比較常見常見的例子,比如你去面試之后,...

    tommego 評論0 收藏0
  • 設計模式察者設計模式

    摘要:關鍵概念理解觀察者設計模式中主要區(qū)分兩個概念觀察者指觀察者對象,也就是消息的訂閱者被觀察者指要觀察的目標對象,也就是消息的發(fā)布者。 原文首發(fā)于微信公眾號:jzman-blog,歡迎關注交流! 最近補一下設計模式相關的知識,關于觀察者設計模式主要從以下幾個方面來學習,具體如下: 什么是觀察者設計模式 關鍵概念理解 通知觀察者的方式 觀察者模式的實現(xiàn) 觀察者模式的優(yōu)缺點 使用場景 下面...

    NotFound 評論0 收藏0
  • 設計模式系列察者模式

    本文從jdk內(nèi)置的觀察者模式來介紹觀察者模式。業(yè)務場景:當老師進門的時候,班長帶頭叫老師好,然后全班同學一起交老師好因為太簡單,直接上代碼 班長繼承自Observable package Observer; import java.util.Observable; import java.util.Observer; public class Monitor extends Observabl...

    Edison 評論0 收藏0
  • Java設計模式察者模式詳解

    摘要:觀察者模式,是一對多的關系,一個主題對應多個觀察者,當這個主題發(fā)生變化的時候,所有觀察著這個主題的觀察者都會接收到通知來獲悉主題的變化。這就是使用的觀察者模式,下面就讓我們用代碼實現(xiàn)觀察者模式。 觀察者模式,是一對多的關系,一個主題對應多個觀察者,當這個主題發(fā)生變化的時候,所有觀察著這個主題的觀察者都會接收到通知來獲悉主題的變化。 在現(xiàn)實中我們也會遇到許許多多應用觀察者模式的行為,比如...

    dayday_up 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<