image.png

这次我们要写观察者模式、上方的图只是为了表达观察者和发布订阅者模式的区别

观察者模式

  1. // 观察者类
  2. class Observer{
  3. constructor(name, subject){
  4. this.name = name;
  5. this.subject = subject;
  6. this.subject.addObserver(this)
  7. }
  8. // 接收目标变化
  9. update(){
  10. console.log(`${this.name}:目标发生----变化了 ${this.subject.getState()}`)
  11. }
  12. }
  13. // 目标类
  14. class Subject{
  15. constructor(){
  16. this.observer = [];
  17. this.state = '0'
  18. }
  19. getState(){
  20. return this.state;
  21. }
  22. // 改变状态
  23. setState(state){
  24. this.state = state;
  25. // 通知观察者
  26. this.notifyAll()
  27. }
  28. // 添加观察者
  29. addObserver(observer){
  30. this.observer.push(observer);
  31. }
  32. // 通知观察者
  33. notifyAll(){
  34. this.observer.forEach( item => item.update())
  35. }
  36. }
  37. // 目标对象
  38. let subject = new Subject();
  39. // 观察者们
  40. let a = new Observer('a',subject)
  41. let b = new Observer('b',subject)
  42. let c = new Observer('c',subject)
  43. subject.setState('111')

观察者模式:观察者和目标直接进行交互、观察者直接订阅subject、当subect被激活的时候会触发观察者的监听事件

发布订阅模式

  1. class EventBus{
  2. constructor(){
  3. this.callbacks = {}
  4. }
  5. $on(name,fn){
  6. if(!this.callbacks[name]) this.callbacks[name] = [];
  7. this.callbacks[name].push(fn);
  8. }
  9. $emit(name, arg){
  10. if(this.callbacks[name]){
  11. this.callbacks[name].forEach( cb => cb(arg))
  12. }
  13. }
  14. }
  15. let eventBus = new EventBus()
  16. // 页面1---添加event1的订阅
  17. eventBus.$on('event1',(arg)=>{
  18. console.log('页面1----event1变化了',arg)
  19. })
  20. // 页面2 ---添加event1的订阅
  21. eventBus.$on('event1',(arg)=>{
  22. console.log('页面2---event1变化了',arg)
  23. })
  24. // 五秒后发布通知
  25. setTimeout( () =>{
  26. eventBus.$emit('event1',{
  27. data:1111
  28. })
  29. }, 5000)

vue的数据双向绑定和事件总线就是使用这个模式、订阅者订阅某个事件名称标记、发布者直接携带参数广播事件!

总结

优点

  • 抽象耦合:在观察者和被观察者之间,建立了一个抽象的耦合,由于耦合是抽象的,可以很容易的扩展观察者和被观察者
  • 广播通信

    缺点

  • 依赖过多:观察者之间的细节依赖过多,会增加事件消耗和程序的复杂度、这里的 细节依赖 指的是 触发机制 , 触发链条 ; 如果 观察者设置过多 , 每次触发都要花很长时间去处理通知

  • 循环调用:观察者和被观察者之间绝对不允许循环以来、否者二者之前循环调用导致系统奔溃