摘要:下面為學習筆記,對觀察者模式做簡單實現。注冊的事件被觸發后需要執行的動作注冊事件及對應的執行動作觸發事件對比執行事件前后的事件列表內容觀察者模式在解決類的耦合中的應用小例子。
這篇筆記主要記錄學習思路及收獲,分享出來拋磚引玉,如有謬誤或優化空間,歡迎交流。
要理解觀察者模式,可以類比vue中的EventBus,其實就是一個全局的觀察者對象($bus),上面有注冊事件($bus.on())和發送事件($bus.emit())的方法,當然因為需要會注冊很多事件,所以內部還有一個事件列表屬性_events來存儲注冊的事件。下面為學習筆記,對觀察者模式做簡單實現。
基于上面的思路,首先要有一個對象,它有一個私有的列表屬性和對外暴露的兩個方法
let Observer = (()=>{ _events:[]; return { retister:()=>{}, issue:()=>{}, } })()
接下來一步步實現。
首先,觀察者對象內部要有一個存儲事件的列表屬性
let Observer = (()=>{ // 防止事件隊列暴露而被篡改故將事件容器作為靜態私有變量保存 let _events = []; })()
其次是注冊事件的register方法,需要兩個參數:需要觀察的事件名稱type和這個事件被觸發后具體的執行內容fn:
let Observer = (()=>{ // 防止事件隊列暴露而被篡改故將事件容器作為靜態私有變量保存 let _events = {}; return { register: (type,fn)=>{ //如果此消息類型不存在則應該創建一個(判斷對象上是否有某個屬性) // if (typeof(_events[type])==="undefined"){ if (!(type in _events)){ _events[type] = [fn]; } else {//如果此消息類型已存在,則直接將對應動作推入消息隊列 _events[type].push(fn); } }, } })()
再然后就是觸發事件的issue方法,也需要兩個參數:要觸發的事件type及傳遞過去的參數arg
let Observer = (()=>{ // 防止事件隊列暴露而被篡改故將事件容器作為靜態私有變量保存 let _events = {}; return { register: (type,fn)=>{ //如果此消息類型不存在則應該創建一個(判斷對象上是否有某個屬性) // if (typeof(_events[type])==="undefined"){ if (!(type in _events)){ _events[type] = [fn]; } else {//如果此消息類型已存在,則直接將對應動作推入消息隊列 _events[type].push(fn); } }, issue: (type,arg)=>{ // 如果沒有此類型,返回 // if (typeof (_events[type]) === "undefined"){ if (!(type in _events)) { return; } for (let i=0;i<_events[type].length;i++){ _events[type][i](arg); } }, } })()
最后,可以再加一個可以移除已監聽事件的remove方法
let Observer = (()=>{ // 防止事件隊列暴露而被篡改故將事件容器作為靜態私有變量保存 let _events = {}; return { register: (type,fn)=>{ //如果此消息類型不存在則應該創建一個(判斷對象上是否有某個屬性) // if (typeof(_events[type])==="undefined"){ if (!(type in _events)){ _events[type] = [fn]; } else {//如果此消息類型已存在,則直接將對應動作推入消息隊列 _events[type].push(fn); } }, issue: (type,arg)=>{ // 如果沒有此類型,返回 // if (typeof (_events[type]) === "undefined"){ if (!(type in _events)) { return; } for (let i=0;i<_events[type].length;i++){ _events[type][i](arg); } }, // 此方法可以類比document.removerEventListener(evt,fn) remove: (type,fn)=>{ // 如果這個類型的事件存在 if (_events[type] instanceof Array){ for (let i = 0; i < _events[type].length; i++) { _events[type][i] === fn && _events[type].splice(i,1); } } }, // 因為外部獲取不到私有屬性`_events`,所以臨時用這個方法檢查`remove`方法是否生效 check (){ console.log("_events事件隊列",_events); } } })()
至此一個基本的觀察者對象就寫出來了,接下來跑一下看效果。
// 注冊的事件被觸發后需要執行的動作 function handler (val){ console.log("val:",val*2); } // 注冊事件及對應的執行動作 Observer.register("eventName",handler); // 觸發事件 function test (){ Observer.issue("eventName",5); //10 // 對比執行remove事件前后的事件列表內容 Observer.check(); Observer.remove("eventName",fn); observer.check(); }
觀察者模式在解決類的耦合中的應用小例子。想象一下課堂上老師提問,學生回答問題的場景。老師提問的問題名稱相當于發出的事件,如果學生聽到這個問題(事先注冊了這個問題名稱),那么便會回答(響應事件的動作)。
學生類:
let Student = function (result) { // 問題答案 this.result = result; // 回答的動作 this.answer = ()=>{ console.log("答案",this.result); } } Student.prototype.listen = function(question){ Observer.register(question,this.answer); } Student.prototype.sleep = function (question) { Observer.remove(question,this.answer); console.log("這個問題我聽不到聽不到~"); }
教師類:
let Teacher = function (){} // 對某一個問題發出問題 Teacher.prototype.ask = function (question) { Observer.issue(question); }
執行:
let student1 = new Student("學生1回答問題"); let student2 = new Student("學生2回答問題"); let student3 = new Student("學生3:呼嚕呼嚕~"); student1.listen("雞生蛋還是蛋生雞?"); student2.listen("雞生蛋還是蛋生雞?"); student3.listen("雞生蛋還是蛋生雞?"); let teacher = new Teacher(); // 老師發問 function test () { teacher.ask("雞生蛋還是蛋生雞?"); } //答案 學生1回答問題 //es5觀察者.html:68 答案 學生2回答問題 //es5觀察者.html:68 答案 學生3:呼嚕呼嚕~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101560.html
摘要:設計模式與開發實踐讀書筆記。發布訂閱模式又叫觀察者模式,它定義了對象之間的一種一對多的依賴關系。附設計模式之發布訂閱模式觀察者模式數據結構和算法系列棧隊列優先隊列循環隊列設計模式系列設計模式之策略模式 《JavaScript設計模式與開發實踐》讀書筆記。 發布-訂閱模式又叫觀察者模式,它定義了對象之間的一種一對多的依賴關系。當一個對象的狀態發生改變時,所有依賴它的對象都將得到通知。 例...
摘要:觀察者模式應用場景場景一當觀察的數據對象發生變化時自動調用相應函數。比如的雙向綁定場景二每當調用對象里的某個方法時就會調用相應訪問邏輯。 觀察者模式 應用場景: 場景一: 當觀察的數據對象發生變化時, 自動調用相應函數。比如 vue 的雙向綁定;場景二: 每當調用對象里的某個方法時, 就會調用相應訪問邏輯。比如給測試框架賦能的 spy 函數; 場景一: 雙向綁定 Object.defi...
摘要:設計模式與開發實踐讀書筆記。看此文章前,建議先看設計模式之發布訂閱模式觀察者模式在中,已經介紹了什么是發布訂閱模式,同時,也實現了發布訂閱模式。 《JavaScript設計模式與開發實踐》讀書筆記。 看此文章前,建議先看JavaScript設計模式之發布-訂閱模式(觀察者模式)-Part1 在Part1中,已經介紹了什么是發布-訂閱模式,同時,也實現了發布-訂閱模式。但是,就Part1...
摘要:設計模式與開發實踐讀書筆記。看此文章前,建議先看設計模式之發布訂閱模式觀察者模式在中,已經介紹了什么是發布訂閱模式,同時,也實現了發布訂閱模式。 《JavaScript設計模式與開發實踐》讀書筆記。 看此文章前,建議先看JavaScript設計模式之發布-訂閱模式(觀察者模式)-Part1 在Part1中,已經介紹了什么是發布-訂閱模式,同時,也實現了發布-訂閱模式。但是,就Part1...
閱讀 666·2021-11-15 11:37
閱讀 4105·2021-09-09 09:34
閱讀 3559·2019-08-30 15:52
閱讀 2602·2019-08-29 14:03
閱讀 2842·2019-08-26 13:36
閱讀 1587·2019-08-26 12:16
閱讀 1592·2019-08-26 11:45
閱讀 3488·2019-08-23 18:41