亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

觀察者模式(ObserverPattern)

JeOam / 2034人閱讀

摘要:當(dāng)氣象局發(fā)布新的天氣數(shù)據(jù)后,兩個公告牌上顯示的天氣數(shù)據(jù)必須實時更新。氣象局同時要求我們保證程序擁有足夠的可擴(kuò)展性,因為后期隨時可能要新增新的公告牌。

轉(zhuǎn)載請注明出處:https://zhuanlan.zhihu.com/p/20540213
文章中的例子和思路均來自于《Head First》

場景

我們接到一個來自氣象局的需求:氣象局需要我們構(gòu)建一套系統(tǒng),這系統(tǒng)有兩個公告牌,分別用于顯示當(dāng)前的實時天氣和未來幾天的天氣預(yù)報。當(dāng)氣象局發(fā)布新的天氣數(shù)據(jù)(WeatherData)后,兩個公告牌上顯示的天氣數(shù)據(jù)必須實時更新。氣象局同時要求我們保證程序擁有足夠的可擴(kuò)展性,因為后期隨時可能要新增新的公告牌。

概況

這套系統(tǒng)中主要包括三個部分:氣象站(獲取天氣數(shù)據(jù)的物理設(shè)備)、WeatherData(追蹤來自氣象站的數(shù)據(jù),并更新公告牌)、公告牌(用于展示天氣數(shù)據(jù))

WeatherData知道如何跟氣象站聯(lián)系,以獲得天氣數(shù)據(jù)。當(dāng)天氣數(shù)據(jù)有更新時,WeatherData會更新兩個公告牌用于展示新的天氣數(shù)據(jù)。

錯誤示范

我們現(xiàn)來看看隔壁老王的實現(xiàn)思路:

public class WeatherData {

    //實例變量聲明
    ...
    
    public void measurementsChanged() {
    
        float temperature = getTemperature();
        float humidity = getHumidity();
        float pressure = getPressure();
        List forecastTemperatures = getForecastTemperatures();
        
        //更新公告牌
        currentConditionsDisplay.update(temperature, humidity, pressure);
        forecastDisplay.update(forecastTemperatures);
    }
    ...
}

上面這段代碼是典型的針對實現(xiàn)編程,這會導(dǎo)致我們以后增加或刪除公告牌時必須修改程序。我們現(xiàn)在來看看觀察者模式,然后再回來看看如何將觀察者模式應(yīng)用到這個程序。

觀察者模式介紹

觀察者模式面向的需求是:A對象(觀察者)對B對象(被觀察者)的某種變化高度敏感,需要在B變化的一瞬間做出反應(yīng)。舉個例子,新聞里喜聞樂見的警察抓小偷,警察需要在小偷伸手作案的時候?qū)嵤┳ゲ?。在這個例子里,警察是觀察者、小偷是被觀察者,警察需要時刻盯著小偷的一舉一動,才能保證不會錯過任何瞬間。程序里的觀察者和這種真正的【觀察】略有不同,觀察者不需要時刻盯著被觀察者(例如A不需要每隔1ms就檢查一次B的狀態(tài)),二是采用__注冊__(_Register_)或者成為__訂閱__(_Subscribe_)的方式告訴被觀察者:我需要你的某某狀態(tài),你要在它變化時通知我。采取這樣被動的觀察方式,既省去了反復(fù)檢索狀態(tài)的資源消耗,也能夠得到最高的反饋速度。

觀察者模式通?;赺_Subject__和__Observer__接口類來設(shè)計,下面是是類圖:

觀察者模式的應(yīng)用

結(jié)合上面的類圖,我們現(xiàn)在將觀察者模式應(yīng)用到WeatherData項目中來。于是有了下面這張類圖:

主題接口

/**
 * 主題(發(fā)布者、被觀察者)
 */
public interface Subject {

    /**
     * 注冊觀察者
     */
    void registerObserver(Observer observer);

    /**
     * 移除觀察者
     */
    void removeObserver(Observer observer);

    /**
     * 通知觀察者
     */
    void notifyObservers(); 
}

觀察者接口

/**
 * 觀察者
 */
public interface Observer {
    void update();
}

公告牌用于顯示的公共接口

public interface DisplayElement {
    void display();
}

下面我們再來看看WeatherData是如何實現(xiàn)的

public class WeatherData implements Subject {

    private List observers;

    private float temperature;//溫度
    private float humidity;//濕度
    private float pressure;//氣壓
    private List forecastTemperatures;//未來幾天的溫度

    public WeatherData() {
        this.observers = new ArrayList();
    }

    @Override
    public void registerObserver(Observer observer) {
        this.observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        this.observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }

    public void setMeasurements(float temperature, float humidity, 
    float pressure, List forecastTemperatures) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        this.forecastTemperatures = forecastTemperatures;
        measurementsChanged();
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }

    public List getForecastTemperatures() {
        return forecastTemperatures;
    }
}

顯示當(dāng)前天氣的公告牌CurrentConditionsDisplay

public class CurrentConditionsDisplay implements Observer, DisplayElement {

    private WeatherData weatherData;

    private float temperature;//溫度
    private float humidity;//濕度
    private float pressure;//氣壓

    public CurrentConditionsDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        this.weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("當(dāng)前溫度為:" + this.temperature + "℃");
        System.out.println("當(dāng)前濕度為:" + this.humidity);
        System.out.println("當(dāng)前氣壓為:" + this.pressure);
    }

    @Override
    public void update() {
        this.temperature = this.weatherData.getTemperature();
        this.humidity = this.weatherData.getHumidity();
        this.pressure = this.weatherData.getPressure();
        display();
    }
}

顯示未來幾天天氣的公告牌ForecastDisplay

public class ForecastDisplay implements Observer, DisplayElement {

    private WeatherData weatherData;

    private List forecastTemperatures;//未來幾天的溫度

    public ForecastDisplay(WeatherData weatherData) {
        this.weatherData = weatherData;
        this.weatherData.registerObserver(this);
    }

    @Override
    public void display() {
        System.out.println("未來幾天的氣溫");
        int count = forecastTemperatures.size();
        for (int i = 0; i < count; i++) {
            System.out.println("第" + i + "天:" + forecastTemperatures.get(i) + "℃");
        }
    }

    @Override
    public void update() {
        this.forecastTemperatures = this.weatherData.getForecastTemperatures();
        display();
    }
}

到這里,我們整個氣象局的WeatherData應(yīng)用就改造完成了。兩個公告牌CurrentConditionsDisplayForecastDisplay實現(xiàn)了ObserverDisplayElement接口,在他們的構(gòu)造方法中會調(diào)用WeatherDataregisterObserver方法將自己注冊成觀察者,這樣被觀察者WeatherData就會持有觀察者的應(yīng)用,并將它們保存到一個集合中。當(dāng)被觀察者`WeatherData狀態(tài)發(fā)送變化時就會遍歷這個集合,循環(huán)調(diào)用觀察者公告牌更新數(shù)據(jù)的方法。后面如果我們需要增加或者刪除公告牌就只需要新增或者刪除實現(xiàn)了ObserverDisplayElement接口的公告牌就好了。

觀察者模式將觀察者和主題(被觀察者)徹底解耦,主題只知道觀察者實現(xiàn)了某一接口(也就是Observer接口)。并不需要觀察者的具體類是誰、做了些什么或者其他任何細(xì)節(jié)。任何時候我們都可以增加新的觀察者。因為主題唯一依賴的東西是一個實現(xiàn)了Observer接口的對象列表。

好了,我們測試下利用觀察者模式重構(gòu)后的程序:

public class ObserverPatternTest {

    public static void main(String[] args) {

        WeatherData weatherData = new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

        List forecastTemperatures = new ArrayList();
        forecastTemperatures.add(22f);
        forecastTemperatures.add(-1f);
        forecastTemperatures.add(9f);
        forecastTemperatures.add(23f);
        forecastTemperatures.add(27f);
        forecastTemperatures.add(30f);
        forecastTemperatures.add(10f);
        weatherData.setMeasurements(22f, 0.8f, 1.2f, forecastTemperatures);
    }
}

輸出結(jié)果:

當(dāng)前溫度為:22.0℃
當(dāng)前濕度為:0.8
當(dāng)前氣壓為:1.2
未來幾天的氣溫
第0天:22.0℃
第1天:-1.0℃
第2天:9.0℃
第3天:23.0℃
第4天:27.0℃
第5天:30.0℃
第6天:10.0℃

源碼地址:https://github.com/BaronZ88/DesignPatterns/tree/master/src/com/baron/patterns/observer

如果大家喜歡這一系列的文章,歡迎關(guān)注我的知乎專欄和GitHub。

知乎專欄:https://zhuanlan.zhihu.com/baron

GitHub:https://github.com/BaronZ88

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/66517.html

相關(guān)文章

  • 設(shè)計模式察者設(shè)計模式

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

    NotFound 評論0 收藏0
  • 設(shè)計模式察者模式與發(fā)布訂閱模式

    摘要:觀察者模式與發(fā)布訂閱的區(qū)別在模式中,知道,同時還保留了的記錄。發(fā)布者訂閱者在大多情況下是異步方式使用消息隊列。圖片源于網(wǎng)絡(luò)侵權(quán)必刪如果以結(jié)構(gòu)來分辨模式,發(fā)布訂閱模式相比觀察者模式多了一個中間件訂閱器,所以發(fā)布訂閱模式是不同于觀察者模式的。 學(xué)習(xí)了一段時間設(shè)計模式,當(dāng)學(xué)到觀察者模式和發(fā)布訂閱模式的時候遇到了很大的問題,這兩個模式有點類似,有點傻傻分不清楚,博客起因如此,開始對觀察者和發(fā)布...

    BaronZhang 評論0 收藏0
  • 設(shè)計模式 -- 察者模式

    摘要:總結(jié)一下從表面上看觀察者模式里,只有兩個角色觀察者被觀察者而發(fā)布訂閱模式,卻不僅僅只有發(fā)布者和訂閱者兩個角色,還有第三個角色經(jīng)紀(jì)人存在。參考鏈接觀察者模式發(fā)布訂閱模式 做了這么長時間的 菜鳥程序員 ,我好像還沒有寫過一篇關(guān)于設(shè)計模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設(shè)計模式在從頭學(xué)習(xí)一遍,不然都對不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...

    chengtao1633 評論0 收藏0
  • 設(shè)計模式 -- 察者模式

    摘要:總結(jié)一下從表面上看觀察者模式里,只有兩個角色觀察者被觀察者而發(fā)布訂閱模式,卻不僅僅只有發(fā)布者和訂閱者兩個角色,還有第三個角色經(jīng)紀(jì)人存在。參考鏈接觀察者模式發(fā)布訂閱模式 做了這么長時間的 菜鳥程序員 ,我好像還沒有寫過一篇關(guān)于設(shè)計模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設(shè)計模式在從頭學(xué)習(xí)一遍,不然都對不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...

    makeFoxPlay 評論0 收藏0

發(fā)表評論

0條評論

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