摘要:概念觀察者模式屬于行為模式,是定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,以便當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)刷新。觀察者模式符合接口隔離原則,實(shí)現(xiàn)了對(duì)象之間的松散耦合。
概念
觀察者模式屬于行為模式,是定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,以便當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并自動(dòng)刷新。
當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變后,會(huì)影響到其他幾個(gè)對(duì)象的改變,這時(shí)候可以用觀察者模式。
觀察者模式符合接口隔離原則,實(shí)現(xiàn)了對(duì)象之間的松散耦合。
別名發(fā)布-訂閱
模型-視圖
源-收聽(tīng)者
從屬者模式
角色抽象主題(Subject):它把所有觀察者對(duì)象的引用保存到一個(gè)聚集里,每個(gè)主題都可以有任何數(shù)量的觀察者。抽象主題提供一個(gè)接口,可以增加和刪除觀察者對(duì)象。
具體主題(ConcreteSubject):將有關(guān)狀態(tài)存入具體觀察者對(duì)象;在具體主題內(nèi)部狀態(tài)改變時(shí),給所有登記過(guò)的觀察者發(fā)出通知。
抽象觀察者(Observer):為所有的具體觀察者定義一個(gè)接口,在得到主題通知時(shí)更新自己。
具體觀察者(ConcreteObserver):實(shí)現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題狀態(tài)協(xié)調(diào)。
UML圖 代碼 示例代碼在PHP SPL中已經(jīng)提供SplSubject和SqlOberver接口,源碼如下:
/** * The SplSubject interface is used alongside * SplObserver to implement the Observer Design Pattern. * @link http://php.net/manual/en/class.splsubject.php */ interface SplSubject { /** * Attach an SplObserver * @link http://php.net/manual/en/splsubject.attach.php * @param SplObserver $observer* The SplObserver to attach. *
* @return void * @since 5.1.0 */ public function attach (SplObserver $observer); /** * Detach an observer * @link http://php.net/manual/en/splsubject.detach.php * @param SplObserver $observer* The SplObserver to detach. *
* @return void * @since 5.1.0 */ public function detach (SplObserver $observer); /** * Notify an observer * @link http://php.net/manual/en/splsubject.notify.php * @return void * @since 5.1.0 */ public function notify (); } /** * The SplObserver interface is used alongside * SplSubject to implement the Observer Design Pattern. * @link http://php.net/manual/en/class.splobserver.php */ interface SplObserver { /** * Receive update from subject * @link http://php.net/manual/en/splobserver.update.php * @param SplSubject $subject* The SplSubject notifying the observer of an update. *
* @return void * @since 5.1.0 */ public function update (SplSubject $subject); }
下面我們根據(jù)這兩個(gè)spl接口,寫自己的代碼:
_observers)) { $this->_observers[] = $observer; } } /** * 實(shí)現(xiàn)移除觀察者方法 * * @param SplObserver $observer */ public function detach(SplObserver $observer) { if (false !== ($index = array_search($observer, $this->_observers))) { unset($this->_observers[$index]); } } /** * 實(shí)現(xiàn)提示信息方法 */ public function notify() { foreach ($this->_observers as $observer) { $observer->update($this); } } /** * 設(shè)置數(shù)量 * * @param $count */ public function setCount($count) { echo "數(shù)據(jù)量加" . $count . "運(yùn)行結(jié)果
"; } /** * 設(shè)置積分 * * @param $integral */ public function setIntegral($integral) { echo "積分量加" . $integral . "
"; } } /** * Class Observer1 觀察者一 */ class Observer1 implements SplObserver { public function update(SplSubject $subject) { $subject->setCount(10); } } /** * Class Observer2 觀察者二 */ class Observer2 implements SplObserver { public function update(SplSubject $subject) { $subject->setIntegral(10); } } /** * Class Client 客戶端 */ class Client { /** * 測(cè)試方法 */ public static function test() { // 初始化主題 $subject = new Subject(); // 初始化觀察者一 $observer1 = new Observer1(); // 初始化觀察者二 $observer2 = new Observer2(); // 添加觀察者一 $subject->attach($observer1); // 添加觀察者二 $subject->attach($observer2); // 消息提示 $subject->notify();//輸出:數(shù)據(jù)量加1 積分量加10 // 移除觀察者一 $subject->detach($observer1); // 消息提示 $subject->notify();//輸出:數(shù)據(jù)量加1 積分量加10 積分量加10 } } // 執(zhí)行測(cè)試 Client::test();
數(shù)據(jù)量加10 積分量加10 積分量加10優(yōu)點(diǎn)和缺點(diǎn) 優(yōu)點(diǎn)
觀察者和主題之間的耦合度較?。?/p>
支持廣播通信;
缺點(diǎn)由于觀察者并不知道其它觀察者的存在,它可能對(duì)改變目標(biāo)的最終代價(jià)一無(wú)所知。這可能會(huì)引起意外的更新。
適用場(chǎng)景當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一個(gè)方面。
當(dāng)對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象,而不知道具體有多少個(gè)對(duì)象待改變。
當(dāng)一個(gè)對(duì)象必須通知其它對(duì)象,而它又不能假定其它對(duì)象是誰(shuí)。換句話說(shuō),你不希望這些對(duì)象是緊密耦合的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/22051.html
摘要:我們今天也來(lái)做一個(gè)萬(wàn)能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對(duì)容器接口對(duì)象進(jìn)行操作,第二類是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...
摘要:我們今天也來(lái)做一個(gè)萬(wàn)能遙控器設(shè)計(jì)模式適配器模式將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。今天要介紹的仍然是創(chuàng)建型設(shè)計(jì)模式的一種建造者模式。設(shè)計(jì)模式的理論知識(shí)固然重要,但 計(jì)算機(jī)程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計(jì)模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對(duì)容器接口對(duì)象進(jìn)行操作,第二類是返回一個(gè)容器接口對(duì)象,上節(jié)我們介紹了...
摘要:你好,是我琉憶,程序員面試筆試系列圖書的作者。建造者模式介紹建造者模式又名生成器模式,是一種對(duì)象構(gòu)建模式。表示被構(gòu)造的復(fù)雜對(duì)象。創(chuàng)建該產(chǎn)品的內(nèi)部表示并定義它的裝配過(guò)程。 你好,是我琉憶,PHP程序員面試筆試系列圖書的作者。 本周(2019.3.11至3.15)的一三五更新的文章如下: 周一:PHP面試??贾O(shè)計(jì)模式——工廠模式周三:PHP面試常考之設(shè)計(jì)模式——建造者模式周五:PHP面...
摘要:最近在學(xué)的設(shè)計(jì)模式,看到了觀察者模式,在此寫下一點(diǎn)理解問(wèn)題假如一個(gè)小販,他把產(chǎn)品的價(jià)格提升了,不同的消費(fèi)者會(huì)對(duì)此產(chǎn)生不同的反應(yīng)。 最近在學(xué)php 的設(shè)計(jì)模式, 看到了觀察者模式,在此寫下一點(diǎn)理解: 問(wèn)題: 假如一個(gè)小販, 他把產(chǎn)品的價(jià)格提升了, 不同的消費(fèi)者會(huì)對(duì)此產(chǎn)生不同的反應(yīng)。一般的編程模式無(wú)非是獲取提升的價(jià)格,然后獲取所有的消費(fèi)者,再循環(huán)每個(gè)消費(fèi)者, 不同的消費(fèi)者根據(jù)價(jià)格漲幅...
摘要:觀察者模式解決的問(wèn)題在我們的開(kāi)發(fā)過(guò)程中,應(yīng)該都或多或少的碰到過(guò)改動(dòng)其中一部分代碼會(huì)引起其他一連串改變的問(wèn)題,顯然想要完全避免這種情況不太可能,但我們也應(yīng)答盡量減少對(duì)其他組件的依賴,而觀察者模式就是為了解決這個(gè)問(wèn)題。 觀察者模式解決的問(wèn)題 在我們的開(kāi)發(fā)過(guò)程中,應(yīng)該都或多或少的碰到過(guò)改動(dòng)其中一部分代碼會(huì)引起其他一連串改變的問(wèn)題,顯然想要完全避免這種情況不太可能,但我們也應(yīng)答盡量減少對(duì)其他組...
閱讀 3776·2021-11-11 11:00
閱讀 2245·2021-10-08 10:05
閱讀 2944·2021-10-08 10:04
閱讀 3276·2021-09-30 09:48
閱讀 3970·2021-09-27 14:10
閱讀 1784·2021-09-09 09:33
閱讀 2185·2019-08-30 15:55
閱讀 1662·2019-08-30 13:53