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