乐趣区

关于前端:js实现发布订阅模式和观察者模式有什么区别

公布订阅模式

  1. 利用场景:vue 事件监听(兄弟组件之间传递数据)、nodejs 事件监听
  2. 成员:
  3. 发布者:在发布者中调用 notify()
  4. 订阅者:在订阅者中调用 addSub()
  5. 事件核心:subs 数组、addSub()(也对应 on)、notify()(对应 emit)
// 事件核心
let eventHub = new Vue()

// 组件 A:发布者
addTodo: function (){eventHub.$emit('add-todo', { text: this.newTodoText})
    this.newTodoText = ''
}

// 组件 B:订阅者
created: function (){eventHub.$on('add-todo',(e)=>{})
}
  1. 模仿实现代码:

    <!DOCTYPE html>
    <html>
    <head>
     <meta charset='utf-8'>
     <meta http-equiv='X-UA-Compatible' content='IE=edge'>
     <title> 公布订阅模式 </title>
     <meta name='viewport' content='width=device-width, initial-scale=1'>
    </head>
    
    <script>
    
     // 公布订阅模式事件核心类
     class PublishSubscribe{constructor(){this.subs = {} // Object.create(null)
         }
         // 订阅
         addSub(eventType, handler) {this.subs[eventType] = this.subs[eventType] || []
             this.subs[eventType].push(handler)
         }
         // 公布
         notify(eventType){if(this.subs[eventType]){this.subs[eventType].forEach(handler => {handler()
                 })
             }
         }
     }
    
     // 公布订阅模式应用示例
     // 1、vm 为事件核心实例对象
     let vm = new PublishSubscribe()
    
     // 2、订阅音讯(在订阅者中调用,例如某个组件 1 中)vm.addSub("click",()=>{console.log("click1")
     })
    
     vm.addSub("click",()=>{console.log("click2")
     })
    
     vm.addSub("change",()=>{console.log("change1")
     })
    
     // 3、公布音讯(在发布者中调用,例如某个组件 2 中)vm.notify("click")
     vm.notify("change")
    
    
    
    </script>
    <body>
     
    </body>
    </html>
    

    观察者模式

  2. 利用场景:vue 响应式原理
  3. 成员:
  4. 发布者:为一个对象,领有 subs 数组、addSub()、notify()
  5. 订阅者(观察者):为一个对象,必须领有 update()
  6. 模仿实现代码

    <!DOCTYPE html>
    <html>
    <head>
     <meta charset='utf-8'>
     <meta http-equiv='X-UA-Compatible' content='IE=edge'>
     <title> 观察者模式 </title>
     <meta name='viewport' content='width=device-width, initial-scale=1'>
    </head>
    
    <script>
     // 1、发布者
     class Dep{constructor(){this.subs = []
         }
    
         addSub (sub){if(sub && sub.update)
                 this.subs.push(sub)
         }
    
         notify (){this.subs.forEach(sub => sub.update())
         }
     }
     // 2、订阅者、观察者
     class Watcher{constructor(name){this.name = name}
         update(){console.log("update:", this.name)
         }
     }
    
     // 应用观察者模式
     let watcher1 = new Watcher("观察者 1")
     let watcher2 = new Watcher("观察者 2")
     let dep = new Dep()
    
     dep.addSub(watcher1)
     dep.addSub(watcher2)
     dep.notify()
    
    </script>
    <body>
     
    </body>
    </html>

公布订阅、观察者模式的区别?

公布订阅模式

  1. 有事件核心、发布者、订阅者三个成员;(事件核心的作用能够隔离发布者和订阅者,去除他们之间的依赖),所有的公布和订阅事件须要存储到事件核心外面。
  2. 事件更新 update() 解决逻辑在订阅时的回调函数中执行。
  3. 公布和订阅者是形象的,通常是在办法里调用 addSub() 和 notify()。
  4. 一个发布者多个订阅者:订阅者执行屡次 addSub() 增加定义,发布者调用一个 notify() 告诉更新。

观察者模式

  1. 没有事件核心,只有发布者、订阅者两个成员。
  2. 发布者中存储所有订阅者 subs 且有增加订阅者的 addSub() 办法、告诉订阅者更新的 notify() 办法。订阅者中必须有一个 update() 办法。
  3. 公布和订阅者是一个对象。
  4. 一个发布者多个订阅者:发布者屡次增加观察者 dep.addSub(watcher),发布者告诉 dep.notify() 触发所有订阅者执行 update()。


特地鸣谢:拉勾教育前端高薪训练营;

退出移动版