js設計模式——釋出訂閱模式
阿新 • • 發佈:2020-10-14
概念
釋出訂閱模式又叫觀察者模式,它定義物件間一對多的依賴關係,當一個物件狀態發生改變時,所有依賴於它的物件都將得到通知。
案例
在js設計模式與開發實踐一書中使用的是樓盤資訊更新發布的案例。大概內容是:想要買房的人們會訂閱自己想要的房產資訊,如果房產資訊有更新,就會發布給這些人。
比如佩奇想買一個房子,他可以在售樓處(salesOffices
)去訂閱這類房產訊息,售樓處會將佩奇訂閱的資訊填寫(listen
)在客戶訂閱表中(clientList
),當有房子出來時,售樓處就會發送(trigger
)資訊給佩奇。
主要內容就是:
salesOffices={ clientList:[], listen:function, trigger:function }
程式碼如下:
<!DOCTYPE html> <html> <head> <title>釋出訂閱</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> </body> <script type="text/javascript"> var consoleText=function(text) { // body... let body=document.body; let div=document.createElement('div'); div.innerHTML=text; body.appendChild(div); } //簡單釋出-訂閱模式 var salesOffices={}; salesOffices.clientList=[]; salesOffices.listen=function(fn){ this.clientList.push(fn); } salesOffices.trigger=function(){ for(var i=0,l=this.clientList.length;i<l;i++){ this.clientList[i].apply(this,arguments); } } salesOffices.listen(function(price,s){ consoleText('佩奇您好,現在有新樓盤:價格:'+price+",面積:"+s); }) salesOffices.listen(function(price,s){ consoleText('小紅您好,現在有新樓盤:價格:'+price+",面積:"+s); }) salesOffices.trigger(6000000,120); </script> </html>
如果現在佩奇發現房價太高了,自己的預算只能付得起80平房子的首付,售樓處再給佩奇發120平的房子只會扎佩奇的心,所以佩奇只想訂閱80平的房子的訊息。
這時候只需要將訂閱表分為不同的型別,想要哪種房子的訊息就去哪張表填寫資訊,現在佩奇的資訊只能出現在80平的表上了。
當有80平的資訊出來時,只需給將80平訂閱表的使用者傳送訊息即可
salesOffices={ clientList:{ square80:[], square120:[], }, listen:function, trigger:function }
程式碼如下:
<!DOCTYPE html> <html> <head> <title>釋出訂閱</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> </body> <script type="text/javascript"> var consoleText=function (text) { // body... let body=document.body; let div=document.createElement('div'); div.innerHTML=text; body.appendChild(div); } //可選型別釋出-訂閱模式 var salesOffices={}; salesOffices.clientList={}; salesOffices.listen=function(key,fn){ //將key型別的訂閱儲存起來 if(!this.clientList[key]){ this.clientList[key]=[] } this.clientList[key].push(fn); } salesOffices.trigger=function(){ let key=Array.prototype.shift.call(arguments); fns=this.clientList[key]; if(!fns||fns.length===0){ return false; } for(var i=0,l=fns.length;i<l;i++){ fns[i].apply(this,arguments); } } salesOffices.listen("square80",function(price){ consoleText('小明您好,現在有新樓盤80平:價格:'+price); }) salesOffices.listen("square80",function(price){ consoleText('小李您好,現在有新樓盤80平:價格:'+price); }) salesOffices.listen("square110",function(price){ consoleText('小紅您好,現在有新樓盤110平:價格:'+price); }) salesOffices.trigger("square80",12000000); </script> </html>
佩奇之後找到了心儀的房子,已經不需要售樓處再發訊息了,所以還有取消訂閱的功能。
而這種釋出訂閱的模式很有用,很多行業都可以使用它,所以如果能安裝即用就會很nice
程式碼如下
<!DOCTYPE html> <html> <head> <title>釋出訂閱</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> </body> <script type="text/javascript"> var consoleText=function (text) { // body... let body=document.body; let div=document.createElement('div'); div.innerHTML=text; body.appendChild(div); } //通用釋出訂閱模式 var event={ clientList:{}, listen:function(key,fn){ if(!this.clientList[key]) this.clientList[key]=[]; this.clientList[key].push(fn); }, trigger:function(){ var key=Array.prototype.shift.call(arguments); var fns=this.clientList[key]; if(!fns||fns.length===0) return false; for(var i=0,l=fns.length;i<l;i++){ fns[i].apply(this,arguments); } }, remove:function(key,fn){ //取消訂閱 var fns=this.clientList[key]; if(!fns){// 如果 key 對應的訊息沒有被人訂閱,則直接返回 return false; } if(!fn){ // 如果沒有傳入具體的回撥函式,表示需要取消 key 對應訊息的所有訂閱 fns&&(fns.length=0); }else{ for(var l=fns.length;l>=0;l--){ if(fns[l]===fn){ fns.splice(l,1); } } } } } var installEvent=function(obj){ for(let i in event){ obj[i]=event[i]; } } var salesOffices={}; installEvent(salesOffices); //key的選擇,我覺得應該是某個變化的條件 salesOffices.listen("square80",f1=function(price){ consoleText('小明您好,現在有新樓盤80平:價格:'+price); }) salesOffices.listen("square80",f2=function(price){ consoleText('小李您好,現在有新樓盤80平:價格:'+price); }) salesOffices.listen("square110",f3=function(price){ consoleText('小紅您好,現在有新樓盤110平:價格:'+price); }) salesOffices.remove("square80",f2); salesOffices.trigger("square80",80); </script> </html>