发布订阅模式和观察者模式
1.发布/订阅模式
- 订阅者
- 发布者
- 信号中心
假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern)
个人理解,就是,订阅者是学生家长 , 老师是发布者,公布学生成绩, 班级就是对应每个学生的 信号中心
具体可以看代码
1 <!DOCTYPE html> 2 <html lang="cn"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>发布订阅模式</title> 7 </head> 8 <body> 9 <script> 10 // 事件触发器 11 class EventEmitter { 12 constructor () { 13 // { 'click': [fn1, fn2], 'change': [fn] } 14 //传null,创建的是没有原型的空对象,提升性能 15 this.subs = Object.create(null) 16 } 17 18 // 注册事件 19 $on (eventType, handler) { 20 this.subs[eventType] = this.subs[eventType] || [] 21 this.subs[eventType].push(handler) 22 } 23 24 // 触发事件 25 $emit (eventType) { 26 if (this.subs[eventType]) { 27 this.subs[eventType].forEach(handler => { 28 handler() 29 }) 30 } 31 } 32 } 33 34 // 测试 35 let em = new EventEmitter() 36 em.$on('click', () => { 37 console.log('click1') 38 }) 39 em.$on('click', () => { 40 console.log('click2') 41 }) 42 43 em.$emit('click') 44 </script> 45 </body> 46 </html>
2.观察者模式
- 观察者(订阅者) -- Watcher
update():当事件发生时,具体要做的事情
- 目标(发布者) -- Dep
subs 数组:存储所有的观察者
addSub():添加观察者
notify():当事件发生,调用所有观察者的 update() 方法
- 没有事件中心
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>观察者模式</title> 7 </head> 8 <body> 9 <script> 10 // 发布者-目标 11 class Dep { 12 constructor () { 13 // 记录所有的订阅者 14 this.subs = [] 15 } 16 // 添加订阅者 17 addSub (sub) { 18 if (sub && sub.update) { 19 this.subs.push(sub) 20 } 21 } 22 // 发布通知 23 notify () { 24 this.subs.forEach(sub => { 25 sub.update() 26 }) 27 } 28 } 29 // 订阅者-观察者 30 class Watcher { 31 update () { 32 console.log('update') 33 } 34 } 35 36 // 测试 37 let dep = new Dep() 38 let watcher = new Watcher() 39 40 dep.addSub(watcher) 41 42 dep.notify() 43 </script> 44 </body> 45 </html>
总结:
- 观察者模式是由具体目标调度,比如当事件触发,Dep 就会去调用观察者的方法,所以观察者模式的订阅者与发布者之间是存在依赖的。
- 发布/订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。