您好,登錄后才能下訂單哦!
觀察者模式上篇
觀察者模式原理:
大家好,歡迎來到污污彈公司,最近啊,污污彈接到氣象站的外包項目。
功能比較簡單:
要對外提供天氣接口(溫度、氣壓、濕度)需要實時通知第三方;
還需要實時在市中心公告欄上發布天氣情況。
司小司接到任務開始動手干了。根據Java面向對象特性分析后得到如下信息:
天氣對象:WeatherData
公告板對象:CurrentConditions
天氣更新時候,調用天氣對象的dataChange方法,得到數據后,然后將數據通過display()方法展示出來。
根據上面信息,我們可以創建以下兩個類:
天氣對象:
@Data public class?WeatherDataOO { ? ?public ?WeatherDataOO (){} ? ?public?WeatherDataOO( CurrentCoditionOO currentCoditionOO){ ? ? ? ?this.currentCoditionOO?= currentCoditionOO; ? ?} ? ?/** ? ? *?溫度 ? ? */ ? ?private float?temperatrue; ? ?/** ? ? *?氣壓 ? ? */ ? ?private float?pressure; ? ?/** ? ? *?濕度 ? ? */ ? ?private float?humidity; ? ?/** ? ? *?公告板對象 ? ? */ ? ?private?CurrentCoditionOO?currentCoditionOO; ? ?/** ? ? *?天氣變化時候方法 ? ? */ ? ?public void?dataChange(){ ? ? ? ?currentCoditionOO.update(this.getTemperatrue(),this.getPressure(),this.getHumidity()); ? ?} ? ?/** ? ? *?模擬氣象站數據 ? ? */ ? ?public void?setData(float?temperatrue,float?pressure,float?humidity){ ? ? ? ?this.temperatrue?= temperatrue; ? ? ? ?this.pressure?= pressure; ? ? ? ?this.humidity?= humidity; ? ? ? ?dataChange(); ? ?} } |
公布欄對象具體內容如下:
@Data public class?CurrentCoditionOO { ? ?/** ? ? *?溫度 ? ? */ ? ?private float?temperatrue; ? ?/** ? ? *?氣壓 ? ? */ ? ?private float?pressure; ? ?/** ? ? *?濕度 ? ? */ ? ?private float?humidity; ? ?/** ? ? *?更新天氣的 ? ? */ ? ?public void?update(float?temperatrue,float?pressure,float?humidity){ ? ? ? ?this.temperatrue?= temperatrue; ? ? ? ?this.pressure?= pressure; ? ? ? ?this.humidity?= humidity; ? ? ? ?display(); ? ?} ? ?/** ? ? *?對外展示天氣信息 ? ? */ ? ?public void?display(){ ? ? ? ?System.out.println("****今天天氣信息******"); ? ? ? ?System.out.println("****溫度:"+temperatrue); ? ? ? ?System.out.println("****氣壓:"+pressure); ? ? ? ?System.out.println("****濕度:"+humidity); ? ?} } |
我們進行測試:
運行方法:
數據輸出與預期的一致。就這么簡單的完事了。司小司快樂的下班了,吃炸雞,喝啤酒。
正在嗨的時候,領導來電話了,說有個新公司要對接天氣信息。司小司想,這個簡單,要么新寫個方法,要么在更新天氣時候,新增加。如下圖:
哇嘎嘎,搞定,接著嗨去。可是,一會老板又打電話,有30家要對接!
司小司一聽,慌亂。我勒個去,這要是來一百個對接,然后又有不合作的,需要去掉的。如果每次都修改代碼,重新上線,非瘋掉不可。無法動態添加第三方公司,擴展性很差,需要修改結構了。
重構思考:
哪些變化的?變化部分抽取出來,做成接口,提供。哪些不變化的?經過分析得到:
經常會變化的部分:公告板對象、天氣變化方法
目前公告板一次性把溫度、濕度、氣壓等公告出來了。以后可能只有溫度或者只有濕度公告板或者多個組合的。所以,公告板對象一定會變化的。果斷提取出一個接口。
從上面,我們可以看出,新接入一家,dataChange方法就要修改一次。所以這個也要抽取出來。
這里司小司打算引進觀察者模式來經行處理。
先來看看什么是觀察者模式:
簡單理解,觀察者模式就像我們在學校訂閱雜志、報刊或者是定牛奶一樣,或者就像我們訂閱的公眾號一樣。先和提供方談好條件,留下聯系地址、聯系人等信息。每天或固定時間,將最新信息送到指定位置。就像公眾號,每天推送消息一樣。
我們就以定牛奶業務為例來說說觀察者模式。
定奶業務有兩個角色:奶站(subject)、用戶(Observer)
來看看這個兩個角色主要功能:
subject:奶站,能夠登記注冊用戶信息(registerObserver)、刪除用戶信息(移除:removeObserver)和給用戶提供新的牛奶(通知:notifyObservers)
根據上面說的,我們可以得到subject接口
對應用戶來說,主要功能,就是接收奶站提供的牛奶。
Observer:接收輸入信息。
所以我們可以得到Observer接口:
舉例圖說:
通過上面舉例,我們知道明白了觀察者模式了吧。
總結,觀察者模式:對象之間多對一依賴的一種設計方案,被依賴的對象為Subject,依賴的對象為Observer,兩者之間的關系:subject通知Observer變化。
根據上面觀察者模式的分析,司小司決定用觀察者模式重新設計方案類圖。如下:
類之間關系說明:
subject:實現了subject接口的weatherDataSt(新天氣)對象。
observer:實現了observer的currentConditions(新公告板)對象。
其中,由新公告板指向新天氣對象的箭頭,表示observer向subject注冊或者申請注銷操作
由新天氣對象指向新公告板對象的箭頭,表示subject通知observer信息。
使用觀察者模式具體代碼實現:
先看項目結構:
結構說明:
interfaceObj:存放接口的包
????Observer:observer接口對象
????Subject:subject接口對象
CurrentConditionSt:實現了Observer接口的公告板對象
ForcastConditionSt:另一個實現了Observer接口的公告板對象(預測公告板)
ObserverWeatherMainTest:觀察者模式的測試類
WeatherDataSt:實現了Subject接口的天氣對象
Observer類里面代碼:
Subject類里面代碼:
CurrentConditionSt類里面代碼:
ForcastConditionSt類里面代碼:
新天氣對象代碼:
測試類里面代碼:
運行結果:
注冊了不同的公告板。打印出結果一不一樣。達到我們預期的結果了。
聯系凱哥--》凱哥Java(kaigejava)
個人博客:www.kaigejava.com
好了,本文就講解到這里。在下一篇文章中,我們將要講解的是:對觀察者模式總結及在Java中內置的觀察者模式
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。