摘要:今天說說觀察者模式,這是一個非常常見的模式,很多事件的分發都基于此模式。這里將從一個題目來說說此模式的使用,有這樣一道題某市一家報社開張,市民訂閱報紙,嘗試使用觀察者模式解決此問題。在使用觀察者模式前,先說說普通的處理方法。
今天說說觀察者模式,這是一個非常常見的模式,很多事件的分發都基于此模式。
這里將從一個題目來說說此模式的使用,有這樣一道題:
某市一家報社開張,市民訂閱報紙,嘗試使用觀察者模式解決此問題。
在使用觀察者模式前,先說說普通的處理方法。
class Publisher { public $title = ""; public function __construct($title) { $this->title = $title; } public function push() { echo "【{$this->title}】發布新聞" . PHP_EOL; } } class People { public $name = ""; public function __construct($name) { $this->name = $name; } public function pull(Publisher $publisher) { echo "【{$this->name}】接收到【{$publisher->title}】發布的新聞" . PHP_EOL; } } /* 初始化用戶 */ $peoples = []; for ($i = 1; $i <= 5; $i++) { $peoples[] = new People("用戶{$i}"); } /* 報社使用 push 方法發布新聞 */ $publisher = new Publisher("報社1"); $publisher->push(); /* 所有訂閱的市民使用 pull 方法接收報社對象 */ foreach ($peoples as $people) { $people->pull($publisher); }
每次 publishier 使用 push 方法,都需要循環一遍 $peoples 進行通知,當然這里可以通過一個函數封裝起來,每次調用即可。
以下是運行截圖:
以上代碼運行肯定是沒有任何問題的,也特別容易理解。只要運行了 push 方法,就循環調用一遍 pull 方法。但每次調用特別麻煩,有么有更好的改進呢?
來看一下接下來的代碼:
class Publisher { public $title = ""; private $peoples = []; public function __construct($title, $peoples) { $this->title = $title; $this->peoples = $peoples; } public function push() { echo "【{$this->title}】發布新聞" . PHP_EOL; // 一旦發布新聞,就通知所有訂閱用戶 foreach ($this->peoples as $people) { // 這里注意有 $this $people->pull($this); } } } // 原先的 People 類不變,此處省略 $peoples = []; for ($i = 1; $i <= 5; $i++) { $peoples[] = new People("用戶{$i}"); } // 創建 $publisher 時,直接將 $peoples 傳給報社 $publisher = new Publisher("報社1", $peoples); $publisher->push();
這里可以看到已經將循環移入了 Publisher 類中,每次只要執行 push 方法,所有的 people 對象都能收到消息。
可是這里 $peoples 是通過構造函數傳進去的,能不能進行分離呢?
下面就改寫一下代碼:
class Publisher { public $title = ""; private $peoples = []; public function __construct($title) { $this->title = $title; } public function addPeople(People $people) { $this->peoples[] = $people; } public function push() { echo "【{$this->title}】發布新聞" . PHP_EOL; foreach ($this->peoples as $people) { $people->pull($this); } } } // 客戶端 $publisher = new Publisher("報社1"); for ($i = 1; $i <= 5; $i++) { $publisher->addPeople(new People("用戶{$i}")); } $publisher->push();
改成這樣后使用非常方便,思路也非常清晰。
以上就是觀察者模式的雛形,接下來就是抽象化了...
interface IObserver { public function update(Publisher $publisher); } class Publisher { public $title = ""; private $observers = []; public function __construct($title) { $this->title = $title; } public function attach(IObserver $observer) { $this->observers[] = $observer; } public function push() { echo "【{$this->title}】發布新聞" . PHP_EOL; foreach ($this->observers as $observer) { $observer->update($this); } } } class People implements IObserver { public $name = ""; public function __construct($name) { $this->name = $name; } public function update(Publisher $publisher) { echo "【{$this->name}】接收到【{$publisher->title}】發布的新聞" . PHP_EOL; } } $publisher = new Publisher("報社1"); for ($i = 1; $i <= 5; $i++) { $publisher->attach(new People("用戶{$i}")); } $publisher->push();
以上就是比較標準的觀察者模式結構,其中需要說明的是在 IObserver 接口中定義的 update 方法參數是可以根據場景需要進行修改的。
另一個需要說的是在 Publisher 類中,可以創建一個 detach 方法用于退訂。這樣整個對于 $peoples 的管理就相對完整一些了。
其實有時候覺得學習設計模式不要學的太死了,只要思路對,怎么寫都可以。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/31403.html
摘要:修改配置遠比修改源代碼要簡單的多。在年提出了種設計模式。常用的設計模式及設計原則可以參考下面的思維導圖。每種設計模式都有它的適應場景,有的場景也會使用多種設計模式。包含文章視頻源代碼原創新書移動前端高效開發實戰已在亞馬遜京東當當開售。 作者:曉飛本文原創,轉載請注明作者及出處 在后端語言中,設計模式應用的較為廣泛。如Spring中常見的工廠模式、裝飾者模式、單例模式、迭代器模式。但是...
摘要:文章一步步做組件學校選擇器版本添加自定義事件,即使用觀察者模式。文章一步步做組件學校選擇器版本后增實現學校選擇器的模態對話框,并在頁面中共用同一個選擇器對象。監聽時判斷,回調時判斷,文章一步步做組件學校選擇器 前言 年初的時候寫過一個js組件的系列文章,博客原文地址為 http://jsorz.cn/blog/2015/02/step-by-step-js-component-scho...
摘要:從源碼看概念與實現是異步編程中的重要概念,它較好地解決了異步任務中回調嵌套的問題。這些概念中有趣的地方在于,標識狀態的變量如都是形容詞,用于傳入數據的接口如與都是動詞,而用于傳入回調函數的接口如及則在語義上用于修飾動詞的副詞。 從源碼看 Promise 概念與實現 Promise 是 JS 異步編程中的重要概念,它較好地解決了異步任務中回調嵌套的問題。在沒有引入新的語言機制的前提下,這...
摘要:下面為學習筆記,對觀察者模式做簡單實現。注冊的事件被觸發后需要執行的動作注冊事件及對應的執行動作觸發事件對比執行事件前后的事件列表內容觀察者模式在解決類的耦合中的應用小例子。 這篇筆記主要記錄學習思路及收獲,分享出來拋磚引玉,如有謬誤或優化空間,歡迎交流。 要理解觀察者模式,可以類比vue中的EventBus,其實就是一個全局的觀察者對象($bus),上面有注冊事件($bus.on()...
摘要:為解決這問題,我們發現元兇處在一線程一請求上,如果一個線程能同時處理多個請求,那么在高并發下性能上會大大改善。這樣一個線程可以同時發起多個調用,并且不需要同步等待數據就緒。表示當前就緒的事件類型。 JAVA NIO 一步步構建I/O多路復用的請求模型 摘要:本文屬于原創,歡迎轉載,轉載請保留出處:https://github.com/jasonGeng88/blog 文章一:JAVA ...
閱讀 3980·2021-11-16 11:44
閱讀 5235·2021-10-09 09:54
閱讀 2039·2019-08-30 15:44
閱讀 1692·2019-08-29 17:22
閱讀 2765·2019-08-29 14:11
閱讀 3401·2019-08-26 13:25
閱讀 2333·2019-08-26 11:55
閱讀 1603·2019-08-26 10:37