首页 > 技术文章 > 【设计模式】从前端角度理解发布/订阅模式

Shyno 2021-12-16 15:37 原文

!!下面有完整代码

 

需求实例

现有以下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
}

 结果很明显:

     在观察者模式中,观察者列表是被观察者的属性之一,被观察者同时可以操作被观察列表,并且他要自己去通知观察者. (老师给自己的学生布置作业,老师->多位学生)

     在发布/订阅模式中.发布者什么都不用管.订阅者的存储和操作,以及发布通知都是由发布订阅中心来操作的.  (我委托中介帮我租房,我->中介->多个房源)

 

推荐阅读