在我的理解中,觀察者模式,又叫發(fā)布/訂閱模式,是一種是一種很便捷的用于不同模塊之間相互通信的一種方式,類似于事件又不同于事件。
站在用戶的角度思考問題,與客戶深入溝通,找到龍馬潭網(wǎng)站設(shè)計(jì)與龍馬潭網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站制作、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋龍馬潭地區(qū)。
在我目前的理解中,觀察者模式應(yīng)該有三個(gè)部分組成,發(fā)布者,訂閱者,管理平臺(tái),發(fā)布者發(fā)布信息到管理平臺(tái),管理平臺(tái)收集到信息之后分發(fā)給訂閱者,用更淺白的語言來形容我對觀察者模式的理解就是函數(shù)調(diào)用,在不同模塊之間通過函數(shù)調(diào)用進(jìn)行通信。
言語之間不太好解釋,還是來看看代碼,可以更快的理解我所說的意思,先看管理平臺(tái)是如何工作的:
let event = []; class Test{ static addEvent(type,fn){ if(!event[type]){ event[type] = [fn]; }else{ event[type].push(fn); } } static dispath(type){ let s = [] ,i=1; while (arguments[i]) { s.push(arguments[i]); i++; } if(!event[type]){ console.error('no Event!'); }else{ for(let i = 0;i我這里起名字的時(shí)候是用了Event的那一套名字,但和Event那一套其實(shí)沒有什么關(guān)系,完全可以換成不同的名字。
看上面的代碼:
let event = [];這是一個(gè)數(shù)組,用來存放訂閱者的信息,也就是訂閱的事件類型,和觸發(fā)函數(shù),最終所形成的樣式是這樣的:
[ 'type1' : [fn1,fn2,fn3], 'type2' : [fn4], 'type3' : [fn5,fn6] ]實(shí)際上就是有三個(gè)訂閱者訂閱type1,觸發(fā)事件分別為fn1,fn2,fn3,后面等同。當(dāng)發(fā)布者發(fā)布type1的時(shí)候,就會(huì)調(diào)用函數(shù)fn1,fn2,等等。
因?yàn)橛嗛喺唔氁崆坝嗛啿拍芙邮盏奖挥嗛喌膬?nèi)容,所以,我們先看訂閱者是如何訂閱的:
static addEvent(type,fn){ if(!event[type]){ event[type] = [fn]; }else{ event[type].push(fn); } }在node.js中我們聲明了一個(gè)類名為Test,里面有個(gè)靜態(tài)方法 addEvent,兩個(gè)參數(shù),第一個(gè)是訂閱的事件類型,第二個(gè)是觸發(fā)函數(shù),當(dāng)還沒有人訂閱該事件的時(shí)候,就先創(chuàng)建該事件的函數(shù)空間,實(shí)際上就是一個(gè)數(shù)組,把事件名當(dāng)索引,把觸發(fā)事件存到該索引的元素下,如果已經(jīng)有人訂閱了該事件,就直接把觸發(fā)事件push到對應(yīng)索引的元素下。這樣就可以記錄下所有訂閱者訂閱的事件了。
然后是發(fā)布者發(fā)布事件:
static dispath(type){ let s = [] ,i=1; while (arguments[i]) { s.push(arguments[i]); i++; } if(!event[type]){ console.error('no Event!'); }else{ for(let i = 0;i這也是一個(gè)靜態(tài)函數(shù),是用來把發(fā)布者發(fā)布的消息分發(fā)到每一個(gè)訂閱者,while循環(huán)中是對參數(shù)的處理,把除第一個(gè)參數(shù)之外的所有參數(shù)集中到一個(gè)數(shù)組里,方面后面展開,這樣可以還原到發(fā)布消息時(shí)的參數(shù)順序,方面訂閱者更好的接收參數(shù),然后就是在所有的訂閱者中找到第一個(gè)參數(shù)(也就是發(fā)布者發(fā)布的事件)所對應(yīng)的所有觸發(fā)函數(shù),然后循環(huán)調(diào)用一次并把除事件之外的參數(shù)傳過去。
這樣的話,管理平臺(tái)就組建好了。下面就是訂閱,因?yàn)椴幌扔嗛喪遣豢赡苁盏桨l(fā)布者發(fā)布的消息的。
Test.addEvent('A',function (name,age){ console.log('hello,this is "A" Event 1,has arg:','name:',name,'age:',age); }); Test.addEvent('B',function (num){ console.log('hello,this is "B" Event 2,has arg:',num); }); Test.addEvent('C',function (obj){ console.log('hello,this is "C" Event 3,has arg:',obj); }); Test.addEvent('D',function (arr){ console.log('hello,this is "D" Event 4,has arg:',arr); }); Test.addEvent('E',function (date){ console.log('hello,this is "E" Event 5,has arg:',date); });上面我們訂閱了五個(gè)事件,每個(gè)事件所要接收的參數(shù)類型都不一樣。并且訂閱類型A須要接收兩個(gè)參數(shù),
訂閱是不是很簡單?好吧,其實(shí)發(fā)布者更簡單:
Test.dispath('A','xiaoming',17); Test.dispath('B',123); Test.dispath('C',{say:'hello word'}); Test.dispath('D',[1,2,3]); Test.dispath('E',new Date());發(fā)布事件ABCDE,后面跟上發(fā)布的內(nèi)容,然后訂閱者就可以接發(fā)布時(shí)的順序來接收參數(shù)。在項(xiàng)目中的不同模塊之間進(jìn)行通信就變得非常簡單了。
到了這里,我想大家應(yīng)該也都發(fā)現(xiàn)了我所說的訂閱/發(fā)布 實(shí)際上就是函數(shù)調(diào)用是怎么回事了,訂閱者把將要因事件而被觸發(fā)的函數(shù)通過函數(shù)調(diào)用傳到管理平臺(tái)上,發(fā)布者把須要發(fā)布的事件也通過函數(shù)調(diào)用傳到管理平臺(tái)上,然后管理平臺(tái)則根據(jù)不同的事件調(diào)用不同的函數(shù)。
代碼不夠精練,格式不夠標(biāo)準(zhǔn)......
好吧,完了。
------------------------------------------------------------------------------------
另外,記錄一點(diǎn)和該話題沒多大關(guān)系但用到的一點(diǎn)內(nèi)容,就是參數(shù)傳遞那一塊,因?yàn)楣芾砥脚_(tái)不能確定發(fā)布者會(huì)傳多少參數(shù)進(jìn)來,所以用到了Node.js的一個(gè)特性:arguments,在node.js中不論函數(shù)有有沒有聲明接收的參數(shù),每個(gè)函數(shù)中都會(huì)有一個(gè)局部變量arguments,它是一個(gè)object對象,會(huì)把外界調(diào)用該函數(shù)時(shí)所傳進(jìn)來的參數(shù)整合進(jìn)來,然后把傳參的順序做為屬性,比如上面的A事件,在管理平臺(tái)的dispath函數(shù)中arguments就是這個(gè)樣子的:
{ '0' : 'A', ‘1’:‘xiaoming’, '2' : 17 }對象直接用 ... 這個(gè)符號(hào)拆分的話會(huì)報(bào)錯(cuò),所以我把a(bǔ)rguments用while重新組合成了數(shù)組,然后用 ...符號(hào)來拆分?jǐn)?shù)組再進(jìn)行參數(shù)傳遞。
網(wǎng)頁題目:node.js學(xué)習(xí)筆記之淺談?dòng)^察者模式
本文路徑:http://weahome.cn/article/gehcgi.html