!!下面有完整代碼
需求實例
現有以下3個學生
let test1 = {name:'小明',age:18} let test2 = {name:'小紅',age:17} let test3 = {name:'小智',age:16}
然后,我
let me ={ name:'shyno', age:18 }
假如,我希望在"me"進行自我介紹之后,讓其他幾個學生分別進行自我介紹.那我該怎么做?
我們之前說了觀察者模式-----【設計模式】從前端的角度去理解觀察者模式,這次我們嘗試用發布/訂閱模式去解決.如果觀察者模式相當於一個老師管一個班的話,那發布/訂閱模式就是老師和學生都在一個"app"上上網課.
模式分析
發布/訂閱中心(app)
這個app只是得提供兩個功能,1.讓老師提供課程上課(發布),2學生自己選要聽課的老師(訂閱).通知道學生上課了
//抽象化發布/訂閱中心 function publishSubscribe(){ this.List = [] this.subscribe=function(key,fn){ //訂閱,假如"key"老師更新了,這個app將fn } this.release=function(key){ //發布,老師"key"發布自己的課程 } }
然后我們具象化一下這個發布訂閱中心
//發布/訂閱中心 function publishSubscribeSpecific(obj){ publishSubscribe.apply(this) this.name = obj.name this.List = [] //所有學生的訂閱情況 this.subscribe=function(key,fn){ //訂閱后將學生關注的老師以及其對應的老師更新之后他期望的做法都放進this.List里面 this.List.push({ teacher:key, notice:fn }) } this.release=function(key){ //老師通過這個函數發布 //發布完之后 let list = this.List.filter((item)=>item.teacher===key) //去通知所有關注key老師的學生 list.forEach((item)=>{ item.notice() }) } }
到此為止這個發布訂閱中心就完成了,接下來是整個發布和訂閱的流程
let app =new publishSubscribeSpecific({name:'小菊花課堂'}) //實例化一個小菊花課堂 app.subscribe('shyno',()=>{console.log(`小明知道了,馬上開電腦`)}) //小明訂閱了shyno老師 app.subscribe('shyno',()=>{console.log(`小紅知道了,馬上過去聽課`)}) //小紅訂閱了shyno老師 app.subscribe('nico',()=>{console.log(`小智知道了,馬上過去聽課`)}) //小智訂閱了nico老師 app.release('shyno') //shyno老師上線了
執行結果
一個完整的發布和訂閱流程就完成了.
但是,有一個言論的說法是發布/訂閱模式其實就是觀察者模式.為什么?
我們再回到開頭需求里提到的數據
let test1 = {name:'小明',age:18} let test2 = {name:'小紅',age:17} let test3 = {name:'小智',age:16}
到目前為止,我們根本就沒用到這幾個對象,所以我們把這個發布訂閱中心稍微做個修改.
發布/訂閱模式二
完整代碼
//抽象化發布/訂閱中心 function PublishSubscribe(){ this.List = [] this.subscribe=function(obj){ //訂閱,假如"key"老師更新了,這個app將fn } this.release=function(key){ //發布,老師"key"發布自己的課程 } } //發布/訂閱中心 function PublishSubscribeSpecific(obj){ PublishSubscribe.apply(this) this.name = obj.name this.List = [] //所有學生的訂閱情況 this.subscribe=function(obj){ //訂閱后將學生關注的老師以及其對應的老師更新之后他期望的做法都放進this.List里面 this.List.push(obj) } this.release=function(obj){ //老師通過這個函數發布 //發布完之后 console.log(`我的名字是:${obj.name},我的年齡是:${this.age}.我自我介紹完了,輪到你們自我介紹了;`) this.List.forEach((item)=>{ item.notice(obj.name) }) } this.remove = function(obj){ //取消訂閱 this.List= this.List.filter((item)=>item!==obj) } } //訂閱者 function Student(obj){ this.name=obj.name this.age=obj.age this.notice =(data)=>{ console.log(`我收到了${data}的自我介紹邀請,我的名字是${this.name},我的年齡是:${this.age}`) } } //發布者 function Teacher(obj){ this.name=obj.name } /*-------------分割線-------------*/ let test1 = {name:'小明',age:18} let test2 = {name:'小紅',age:17} let test3 = {name:'小智',age:16} let me ={ name:'shyno', age:18 } let student_test1 =new Student(test1) let student_test2 =new Student(test2) let student_test3 =new Student(test3) let teacher_me =new Teacher(me) let app =new PublishSubscribeSpecific({name:'小菊花課堂'}) //實例化一個小菊花課堂 app.subscribe(student_test1) //小明訂閱了 app.subscribe(student_test2) //小紅訂閱了 app.subscribe(student_test3) //小智訂閱了 // app.remove(student_test1) //小明取消訂閱了 app.release(teacher_me) //shyno老師上線了,發布了通知
結果
和觀察者模式是不是很相似?具體可對比我的另一篇博客:【設計模式】從前端的角度去理解觀察者模式,那么他們有什么不同呢?
觀察者模式和發布/訂閱模式的區別
主要在於被觀察者(觀察者模式)和發布者(發布/訂閱模式)的區別
我們先把被觀察者的代碼拷過來看看
被觀察者(可觀察對象)
//可觀察對象 function Observed (obj){ ObserverSpecificListSpecific.apply(this) //被觀察者實際上擁有觀察者列表的所有屬性 this.name =obj.name //同時被觀察者有自己特有的屬性和函數 this.age =obj.age //重寫say this.say=function(data){ console.log(`我的名字是:${this.name},我的年齡是:${this.age}.我自我介紹完了,輪到你們自我介紹了;`) this.update() } }
發布者
function Teacher(obj){ this.name=obj.name }
結果很明顯:
在觀察者模式中,觀察者列表是被觀察者的屬性之一,被觀察者同時可以操作被觀察列表,並且他要自己去通知觀察者. (老師給自己的學生布置作業,老師->多位學生)
在發布/訂閱模式中.發布者什么都不用管.訂閱者的存儲和操作,以及發布通知都是由發布訂閱中心來操作的. (我委托中介幫我租房,我->中介->多個房源)