摘要:這是一個設(shè)計模式系列本書所有案例均來自設(shè)計模式中文版地址歡迎大家觀察者模式定義了對象之間的一對多依賴當(dāng)一個對象改變狀態(tài)時它的所有依賴者都將會收到通知并自動更新觀察者模式形容圖設(shè)計謎題有一個氣象觀察站我們希望建立一個應(yīng)用有三種布告板用于顯示
觀察者模式這是一個設(shè)計模式系列,本書所有案例均來自「Head-First設(shè)計模式(中文版)」, Github地址, 歡迎大家 watch, star
定義了對象之間的一對多依賴,當(dāng)一個對象改變狀態(tài)時,它的所有依賴者都將會收到通知并自動更新.
觀察者模式形容圖
設(shè)計謎題有一個氣象觀察站,我們希望建立一個應(yīng)用,有三種布告板(用于顯示不同的氣象數(shù)據(jù)),當(dāng)氣象站獲取到最新的測量數(shù)據(jù)時,我們希望三種布告板能實時更新.
類圖設(shè)計
其中 WeatherData用于獲取氣象站最新測量數(shù)據(jù)(三個get方法),當(dāng)數(shù)據(jù)更新時,會調(diào)用onChanged方法(不要管為什么,這是氣象站內(nèi)部邏輯).
代碼實現(xiàn)
主題接口
interface Sublect { public function registerObserver(Observer $observer); public function removeObserver(); public function nitifyObservers(); }
主題對象 WeatherData
class WeatherData implements Sublect { protected $observers = []; protected $pressure, $temperature, $humidity; public function registerObserver(Observer $observer) { if (array_search($observer, $this->observers) === false) { $this->observers[] = $observer; } } public function removeObserver() { if (($index = array_search($observer, $this->observers)) !== false) { unset($this->observers[$index]); } } public function nitifyObservers() { foreach ($this->observers as $observer) { $observer->update($this->getPressure(), $this->getTemperature(), $this->getHumidity()); } } public function onChanged() { $this->nitifyObservers(); } //獲取最新氣壓 public function getPressure() { return $this->pressure; } //獲取最新溫度 public function getTemperature() { return $this->temperature; } //獲取最新濕度 public function getHumidity() { return $this->humidity; } //測試 public function youNeedChanged() { $this->pressure = mt_rand(1, 99); $this->temperature = mt_rand(1, 99); $this->humidity = mt_rand(1, 99); $this->onChanged(); } }
觀察者接口
interface Observer { //氣壓/溫度/濕度 public function update($pressure, $temperature, $humidity); }
顯示面板接口
interface DisplayElement { public function display(); }
觀察者對象集
class CurrentConditionsDisplay implements Observer, DisplayElement { protected $subject; protected $pressure, $temperature, $humidity; //這里為什么會保留 Subject 接口的引用是為了方便的 remove 及 registe public function __construct(Sublect $subject) { $this->subject = $subject; $this->subject->registerObserver($this); } public function update($pressure, $temperature, $humidity) { $this->pressure = $pressure; $this->temperature = $temperature; $this->humidity = $humidity; $this->display(); } public function display() { echo "Current pressure: {$this->pressure}, Current temperature: {$this->temperature}"; } } //其他兩種布告板省略
測試
$weatherData = new WeatherData(); $display = new CurrentConditionsDisplay($weatherData);//把當(dāng)前布告欄注冊成為觀察者 //$other = new OthersDisplay($weatherData);//把當(dāng)前布告欄注冊成為觀察者 //$other = new OtherDisplay($weatherData);//把當(dāng)前布告欄注冊成為觀察者 $weatherData->youNeedChanged();//氣象站數(shù)據(jù)更新了會導(dǎo)致布告板實時更新 //Current pressure: 33, Current temperature: 46另一種形式的觀察者模式
我們知道,觀察者總是被動的接受主題對象的推送,但有些場景下,我們希望觀察者能主動的去獲取數(shù)據(jù);畢竟觀察者數(shù)量這么多,主題對象不可能事先知道每個觀察者需要的狀態(tài),并且也不會導(dǎo)致明明只需要一點點數(shù)據(jù),卻被迫收到一堆.
我們來重寫設(shè)計上面的問題.
類圖基本保持不變,只是在WeatherData類新增了setChanged方法并改變了Observer接口update簽名.
重構(gòu)后的主題接口
interface Sublect { public function registerObserver(Observer $observer); public function removeObserver(); public function nitifyObservers($args = null); } interface Observer { public function update(Sublect $subject, $object = null); }
重構(gòu)后的主題對象
class WeatherData implements Sublect { protected $observers = []; protected $pressure, $temperature, $humidity, $changed; public function nitifyObservers($args = null) { if ($this->changed) { foreach ($this->observers as $observer) { $observer->update($this, $args); } $this->changed = false; } } public function onChanged() { $this->setChanged(); $this->nitifyObservers([ "pressure" => $this->pressure, "temperature" => $this->temperature, "humidity" => $this->humidity, ]); } public function setChanged()//新增方法 { $this->changed = true; } //其他方法保持不變 }
重構(gòu)后的布告板對象
class CurrentConditionsDisplay implements Observer, DisplayElement { protected $subject; protected $pressure, $temperature, $humidity; //這里為什么會保留 Subject 接口的引用是為了方便的 remove 及 registe public function __construct(Sublect $subject) { $this->subject = $subject; $this->subject->registerObserver($this); } public function update(Sublect $subject, $object = null) { if ($subject instanceof Sublect) { //你可以用 拉取 的形式獲取最新數(shù)據(jù) $this->pressure = $subject->getPressure(); $this->temperature = $subject->getTemperature(); $this->humidity = $subject->getHumidity(); //也可以從推送數(shù)據(jù)中獲取 $this->pressure = $object["pressure"]; $this->temperature = $object["temperature"]; $this->humidity = $object["humidity"]; } $this->display(); } public function display() { echo "Current pressure: {$this->pressure}, Current temperature: {$this->temperature}"; } }
為什么要加一個 setChanged 方法
setChanged 讓你在更新觀察者時,有更多的彈性,能更適當(dāng)?shù)耐ㄖ^察者,比方說,如果沒有setCanged方法,氣象站溫度變化十分之一度時,都會通知所有觀察者,你肯定不想讓這么頻繁的更新吧.我們可以控制溫度變化達到一度時,調(diào)用setChanged,進行有效的更新.
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/26168.html
摘要:這是一個設(shè)計模式系列本書所有案例均來自設(shè)計模式中文版地址歡迎大家策略模式定義了算法族,分別封裝起來,讓他們之間可以相互調(diào)用,此模式讓算法的變化獨立與調(diào)用算法的客戶端。 這是一個設(shè)計模式系列,本書所有案例均來自「Head-First設(shè)計模式(中文版)」, Github地址, 歡迎大家 watch, star 策略模式 定義了算法族,分別封裝起來,讓他們之間可以相互調(diào)用,此模式讓算法的變化...
摘要:學(xué)習(xí)編程的本最佳書籍這些書涵蓋了各個領(lǐng)域,包括核心基礎(chǔ)知識,集合框架,多線程和并發(fā),內(nèi)部和性能調(diào)優(yōu),設(shè)計模式等。擅長解釋錯誤及錯誤的原因以及如何解決簡而言之,這是學(xué)習(xí)中并發(fā)和多線程的最佳書籍之一。 showImg(https://segmentfault.com/img/remote/1460000018913016); 來源 | 愿碼(ChainDesk.CN)內(nèi)容編輯 愿碼Slo...
摘要:模塊鏈的共識配置,該配置會寫入創(chuàng)世塊。主要指責(zé)是記錄和更新本地累計工作量最高的鏈,并維護鏈上數(shù)據(jù)的索引。消息使用序列化。協(xié)議是節(jié)點之間用來處理廣播和轉(zhuǎn)發(fā)新的交易。 by Nervos CKB Team 在 2017 年底,我們感到心里的一些想法,包括分層的網(wǎng)絡(luò)以及一個作為共同知識庫(Common Knowledge Base)的區(qū)塊鏈,都已經(jīng)成熟。因此 2018 年元旦一過我們就迫不及...
摘要:年,包括分層的網(wǎng)絡(luò)以及一個作為共同知識庫的區(qū)塊鏈,都已經(jīng)成熟。是一個在設(shè)計上非常不同的公有鏈協(xié)議,也是網(wǎng)絡(luò)中的基礎(chǔ)層,是整個加密經(jīng)濟網(wǎng)絡(luò)的信任引擎。主要指責(zé)是記錄和更新本地累計工作量最高的鏈,并維護鏈上數(shù)據(jù)的索引。 說到猿起,這些心里的想法能追溯到 2016 年,甚至更早。2017 年,包括分層的網(wǎng)絡(luò)以及一個作為共同知識庫(Common Knowledge Base)的區(qū)塊鏈,都已經(jīng)成...
摘要:觀察者模式定義設(shè)計模式中對的定義一個對象稱為維持一系列依賴于它觀察者的對象,將有關(guān)狀態(tài)的任何變更自動通知給它們。如圖模式比較觀察者模式則多了一個類似于話題調(diào)度中心的流程,發(fā)布者和訂閱者解耦。 Obeserver(觀察者)模式 定義 《js設(shè)計模式》中對Observer的定義:一個對象(稱為subject)維持一系列依賴于它(觀察者)的對象,將有關(guān)狀態(tài)的任何變更自動通知給它們。 《設(shè)計模...
閱讀 1760·2021-11-25 09:43
閱讀 1797·2021-11-24 10:41
閱讀 3115·2021-09-27 13:36
閱讀 821·2019-08-30 15:53
閱讀 3579·2019-08-30 15:44
閱讀 872·2019-08-30 14:03
閱讀 2583·2019-08-29 16:38
閱讀 1007·2019-08-29 13:23