摘要:一什么是觀察者模式觀察者模式,引用維基百科的說(shuō)法,一個(gè)目標(biāo)對(duì)象管理所有相依與它的觀察者對(duì)象,并在它本身狀態(tài)改變時(shí)發(fā)生通知。四觀察者模式的用途觀察者模式主要用于解耦合,一個(gè)對(duì)象變了,可以通知多個(gè)對(duì)象,而不是在回調(diào)里來(lái)處理各種情況。
一、什么是觀察者模式
觀察者模式,引用維基百科的說(shuō)法,一個(gè)目標(biāo)對(duì)象管理所有相依與它的觀察者對(duì)象,并在它本身狀態(tài)改變時(shí)發(fā)生通知。這通常通過(guò)調(diào)用各觀察者所提供的方法來(lái)實(shí)現(xiàn)。在前端應(yīng)用的范圍還挺多,最常見(jiàn)的事件監(jiān)聽(tīng),addEventListener,我們?cè)谝粋€(gè)元素上注冊(cè)了各類事件,而當(dāng)對(duì)象發(fā)生相應(yīng)改變時(shí),通過(guò)調(diào)用綁定的事件告訴觀察者。就相當(dāng)于在一個(gè)對(duì)象上綁定了各類觀察者。
舉個(gè)與前端不相關(guān)的例子,小偷警察的故事。小偷數(shù)量就是我們這里的目標(biāo)對(duì)象,有三個(gè)警察負(fù)責(zé)看管(觀察者),當(dāng)小偷數(shù)量大于3了,一個(gè)警察要去報(bào)告上級(jí),一個(gè)警察要去警告市民引起重視,一個(gè)去和小偷談話。在程序里通過(guò)調(diào)用這三個(gè)警察的方法來(lái)相當(dāng)于告訴這三個(gè)警察小偷數(shù)量大于3了。
二、用代碼看觀察者模式思路
/* 被觀察類 addObserver()方法把觀察者對(duì)象添加到觀察者對(duì)象列表中 setChange()方法用來(lái)設(shè)置一個(gè)內(nèi)部標(biāo)志位注明數(shù)據(jù)發(fā)生了變化 notifyObservers()方法會(huì)去調(diào)用觀察者對(duì)象列表中所有的Observer的update()方法,通知它們數(shù)據(jù)發(fā)生了變化。 */ function Observable(){ this.observerArray = new Set(); this.updateFlage = false; } Observable.prototype.addObserver = function(data){ this.observerArray.add(data); } Observable.prototype.setChange = function(){ this.updateFlage = true; } Observable.prototype.notifyObservers = function(data){ if(this.updateFlage){ for(let item of this.observerArray){ item.update(data) } } this.updateFlage = false } /* 觀察者類 實(shí)現(xiàn)Observer接口的唯一方法update */ function Observer(){ this.update = function(){ } }
皮一下,這其實(shí)是看了Java里的觀察者模式思想,我用Js實(shí)現(xiàn)了一下。因?yàn)槲铱催@個(gè)實(shí)現(xiàn)思路是更能體會(huì)到觀察者模式的。這里有兩個(gè)類,一個(gè)是被觀察類,實(shí)現(xiàn)了上述三個(gè)方法,一個(gè)是觀察者類。每個(gè)觀察者都有update方法,當(dāng)被觀察者改變了,執(zhí)行相應(yīng)的觀察者的update方法來(lái)通知觀察者被觀察者改變了。下面看示例:
function thief(){ var data = 0; Observable.call(this); this.setData = function(param){ data = param; if(data > 3){ this.setChange(); } this.notifyObservers(); } this.getData = function(){ return data } } thief.prototype = new Observable(); thief.prototype.constructor = thief; let thief1 = new thief(); let police1 = new Observer; let police2 = new Observer; thief1.addObserver(police1) thief1.addObserver(police2) police1.update = function(){ console.log("警察1接收到現(xiàn)在有"+thief1.getData()+"個(gè)小偷") } police2.update = function(){ console.log("警察2接收到現(xiàn)在有"+thief1.getData()+"個(gè)小偷") } thief1.setData(1) //無(wú)輸出 thief1.setData(4) //警察1接收到現(xiàn)在有4個(gè)小偷 警察2接收到現(xiàn)在有4個(gè)小偷
這個(gè)例子小偷繼承了被觀察者,當(dāng)小偷內(nèi)部數(shù)據(jù)大于3的時(shí)候,就通知觀察各個(gè)警察引起重視。因?yàn)槭菂⒄認(rèn)ava的思想來(lái)的,所以看到實(shí)現(xiàn)是通過(guò)將小偷繼承被觀察者類,警察繼承觀察者類。這個(gè)結(jié)構(gòu)其實(shí)用java來(lái)寫(xiě)很清晰,觀察者的模式也體現(xiàn)的很清晰,能幫助我們很好的理解觀察者模式,值得借鑒。比起前端有些寫(xiě)法在被觀察中存入對(duì)應(yīng)的觀察者,和觀察者的回調(diào),這種寫(xiě)法其實(shí)更分離。
三、前端代碼寫(xiě)觀察者模式
前端的寫(xiě)法跟Java里的實(shí)現(xiàn)類是有差別的,看代碼:
/** * 實(shí)現(xiàn)一個(gè)類 * on():存入被觀察者 * fire():手動(dòng)觸發(fā)某個(gè)觀察者,可帶參數(shù) * delete():刪除指定觀察者 * update():被觀察者更新了,執(zhí)行觀察者回調(diào)通知觀察者 * one():某個(gè)觀察者只執(zhí)行一次 * 可鏈?zhǔn)秸{(diào)用 */ function Emiter(){ this.storage = new Map(); } Emiter.prototype.on = function(key,callback){ this.storage.set(key,callback); return this } Emiter.prototype.fire = function(key,data){ this.storage.has(key) ? this.storage.get(key)(data) : console.log("請(qǐng)先注冊(cè)對(duì)應(yīng)的事件"); return this } Emiter.prototype.delete = function(key){ this.storage.has(key) ? this.storage.delete(key) : console.log("請(qǐng)先注冊(cè)對(duì)應(yīng)的事件"); return this } Emiter.prototype.update = function(data){ for (let [key, value] of this.storage) { value(data); } return this } Emiter.prototype.one = function(key,data){ if(this.storage.has(key)){ this.storage.get(key)(data); this.storage.delete(key); }else{ console.log("請(qǐng)先注冊(cè)對(duì)應(yīng)的事件") } return this } //示例 let emiter = new Emiter(); emiter.on("view1",function(data){ console.log("view1收到的數(shù)據(jù)"+data) }) emiter.on("event",function(){ console.log("emiter") }).on("click",function(){ console.log("click啦") }) emiter.update([1,2,3]) //view1收到的數(shù)據(jù)1,2,3 emiter click啦
前端拋開(kāi)一些復(fù)雜規(guī)范性,可以直接把觀察者和觀察者的回調(diào)保存在被觀察者里,當(dāng)被觀察者更新了,執(zhí)行所有觀察者的回調(diào)。這里之所以有one fire 等方法提供,主要是考慮前端addEventListner也是采用觀察者模式,所以一起提供了。只不過(guò)更相當(dāng)于一對(duì)一模式,沒(méi)有對(duì)應(yīng)的update,更新所有觀察者的操作。我們這里探討的設(shè)計(jì)模式應(yīng)該是on update delete為主線。
四、觀察者模式的用途
觀察者模式主要用于解耦合,一個(gè)對(duì)象變了,可以通知多個(gè)對(duì)象,而不是在回調(diào)里來(lái)處理各種情況。一個(gè)場(chǎng)景有個(gè)模塊獲取了數(shù)據(jù),其他多個(gè)view層都需要用到這個(gè)數(shù)據(jù)。我們的做法可能是會(huì)在獲取數(shù)據(jù)后的模塊回調(diào)里進(jìn)行各個(gè)view層的處理,那如果后續(xù)某個(gè)模塊的相應(yīng)業(yè)務(wù)變了,我們可能還得回來(lái)改這個(gè)回調(diào)函數(shù)。那如果通過(guò)觀察者模式,我們可以優(yōu)化為,每個(gè)模塊完全分離,當(dāng)數(shù)據(jù)回來(lái)時(shí)告知每個(gè)模塊即可。以后模塊要改變獲取數(shù)據(jù)后的處理,各個(gè)模塊自己去更新。
我現(xiàn)在在想,event對(duì)象,是不是內(nèi)部實(shí)現(xiàn),是在dom改變時(shí)傳的參數(shù),而在調(diào)用相關(guān)事件時(shí)能拿到這個(gè)回調(diào)的參數(shù)。
之前看文檔,Vue里數(shù)據(jù)變了,如何更新view,用的也是觀察者模式,只不過(guò)不是這種實(shí)現(xiàn)代碼,后續(xù)更新。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108225.html
摘要:觀察者模式定義設(shè)計(jì)模式中對(duì)的定義一個(gè)對(duì)象稱為維持一系列依賴于它觀察者的對(duì)象,將有關(guān)狀態(tài)的任何變更自動(dòng)通知給它們。如圖模式比較觀察者模式則多了一個(gè)類似于話題調(diào)度中心的流程,發(fā)布者和訂閱者解耦。 Obeserver(觀察者)模式 定義 《js設(shè)計(jì)模式》中對(duì)Observer的定義:一個(gè)對(duì)象(稱為subject)維持一系列依賴于它(觀察者)的對(duì)象,將有關(guān)狀態(tài)的任何變更自動(dòng)通知給它們。 《設(shè)計(jì)模...
摘要:關(guān)鍵概念理解觀察者設(shè)計(jì)模式中主要區(qū)分兩個(gè)概念觀察者指觀察者對(duì)象,也就是消息的訂閱者被觀察者指要觀察的目標(biāo)對(duì)象,也就是消息的發(fā)布者。 原文首發(fā)于微信公眾號(hào):jzman-blog,歡迎關(guān)注交流! 最近補(bǔ)一下設(shè)計(jì)模式相關(guān)的知識(shí),關(guān)于觀察者設(shè)計(jì)模式主要從以下幾個(gè)方面來(lái)學(xué)習(xí),具體如下: 什么是觀察者設(shè)計(jì)模式 關(guān)鍵概念理解 通知觀察者的方式 觀察者模式的實(shí)現(xiàn) 觀察者模式的優(yōu)缺點(diǎn) 使用場(chǎng)景 下面...
摘要:觀察者模式的使用場(chǎng)景比如你微博關(guān)注了一個(gè)人,那么這個(gè)人發(fā)布的微博就會(huì)推送到你這。 Java設(shè)計(jì)模式之觀察者模式 一直想寫(xiě)一篇學(xué)習(xí)觀察者模式的總結(jié)沒(méi)有契機(jī),今天學(xué)習(xí)阻塞隊(duì)列的原理時(shí)候看到在實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的時(shí)候用到了通知模式,就是所謂的觀察者模式,正好順便整理一下。 1. 簡(jiǎn)介 觀察者模式定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更...
摘要:概念觀察者模式屬于行為模式,是定義對(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ì)象的改變,這...
摘要:最近在學(xué)的設(shè)計(jì)模式,看到了觀察者模式,在此寫(xiě)下一點(diǎn)理解問(wèn)題假如一個(gè)小販,他把產(chǎn)品的價(jià)格提升了,不同的消費(fèi)者會(huì)對(duì)此產(chǎn)生不同的反應(yīng)。 最近在學(xué)php 的設(shè)計(jì)模式, 看到了觀察者模式,在此寫(xiě)下一點(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à)格漲幅...
摘要:監(jiān)聽(tīng)模式又名觀察者模式發(fā)布訂閱模式源監(jiān)聽(tīng)器模式,模式的核心是設(shè)計(jì)時(shí)要區(qū)分誰(shuí)是被觀察者,誰(shuí)是觀察者。 監(jiān)聽(tīng)模式 又名觀察者模式、發(fā)布/訂閱模式、源-監(jiān)聽(tīng)器(Source/Listener)模式,模式的核心是:設(shè)計(jì)時(shí)要區(qū)分誰(shuí)是被觀察者,誰(shuí)是觀察者。被觀察者至少有三個(gè)方法,添加觀察者、刪除觀察者、監(jiān)聽(tīng)目標(biāo)變化并通知觀察者;觀察者這至少包含一個(gè)方法,當(dāng)接收到被觀察者的通知時(shí),做出相應(yīng)的處理(即...
閱讀 2248·2021-11-18 10:02
閱讀 3499·2021-11-15 11:36
閱讀 1124·2019-08-30 14:03
閱讀 741·2019-08-30 11:08
閱讀 2772·2019-08-29 13:20
閱讀 3295·2019-08-29 12:34
閱讀 1382·2019-08-28 18:30
閱讀 1648·2019-08-26 13:34