设计模式(发布-订阅模式)

280 阅读2分钟

前言

设计模式就好比设计师在设计宏伟建筑的设计稿,而发布-订阅模式就是在众多设计风格中的,一种风格。发布-订阅则模式通常是用来定义和处理一对多的依赖关系。

案例解析

最近小区门口新开了一个水果店,超市会有不定期活动,但是搞活动又是不定时的,很顾客就想享受优惠价格,所以有两个解决方案,第一时每天都往水果店跑一下看一看,其次是是水果店留下顾客电话号码,主动发送短信通知。这种场景下可以考虑发布和订阅的设计模式。

观察者模式VS发布-订阅模式

image.png

实际场景分析

浏览器中监听滚动事件,就用到了发布订阅模式

document.body.addEventListener('scroll',function(){
    console.log('发布后触发的时间')
})

页面加载时订阅了scroll滚动事件,当触发了滚动事件之后会通知然后触发对应的回调

简单实现一个订阅发布对象

构建一个订阅发布类,包含订阅功能,和发布功能

  • 场景1:顾客A,顾客B订阅了超市C的活动,然后超市发布活动时,通知A,B客户
class Event{
    constructor(){
        // 订阅列表
        this.listenList = [];
    }
    /*
    *1.订阅
    *2.发布
    *3.取消订阅
    */
   // 订阅手柄
   listen(fn){
        // 收集订阅
        console.log('开始监听了')
        this.listenList.push(fn)
        console.log(this.listenList,'监听列表----')
   }
   // 发布手柄
   trigger(...argumnets){
        for(let i = 0; i < this.listenList.length;i++){
            this.listenList[i](...argumnets)
        }
   }
}
let event = new Event()
//  顾客A订阅
event.listen(function(msg,price){
    console.log('A顾客',msg,price)
})
//  顾客B订阅
event.listen(function(msg,price){
    console.log('B顾客',msg,price)
})
setTimeout(() => {
    event.trigger('超市C活动开始啦','只要1毛钱')
},2000)
  • 场景二:顾客A只想接收水果类优惠活动,顾客B只想接收蔬菜类活动,此时简单的订阅列表无法满足需求,需要将订阅类表分类,即this.listenList = [{'A活动':XXX,'B活动':XXX}],还有场景是顾客C想取消之前的订阅活动
class Event{
    constructor(){
        // 订阅列表
        this.listenList = {};
    }
    /*
    *1.订阅
    *2.发布
    *3.取消订阅
    */
   // 订阅手柄
   /**
    * @param {*订阅事件名} key 
    * @param {*发布后触发的事件} fn 
    */
   listen(key,fn){
        // 收集订阅
        this.listenList[key] = fn;
   }
   // 发布手柄
   /**
    * @param {*通知的活动对象} key 
    * @param  {...any} argumnets 
    */
   trigger(key,...argumnets){
       if(!this.listenList[key]){
        console.log('不存在事件'+ key,'没有订阅或被移除了')
        return;
       }
      this.listenList[key](key,...argumnets)
   }
   // 取消订阅
   remove(key){
    delete this.listenList[key]
   }
}
let event = new Event()
//  顾客A订阅
event.listen('fruits',function(key,msg,price){
    console.log('A顾客',key + msg,price)
})
//  顾客B订阅
event.listen('vegetable',function(key,msg,price){
    console.log('B顾客',key + msg,price)
})
setTimeout(() => {
    event.trigger('fruits' ,'超市C活动开始啦','只要1毛钱')
},2000)
setTimeout(() => {
    event.trigger('vegetable' , '超市C活动开始啦','只要1毛钱')
},4000)
setTimeout(() => {
    event.remove('vegetable')
},5000)
setTimeout(() => {
    event.trigger('vegetable' , '移除超市C活动开始啦','哈哈哈')
},6000)

总结

发布订阅模式优点:1.时间上解耦,2.对象之前解耦