一看就懂的 JavaScript设计模式之观察者模式

131 阅读3分钟

观察者者模式

定义

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态上发生变化时,会通知所有观察者对象,让他们能够自动更新自己。

场景

  • 宗门任务大殿

    • 维护拥有订阅权限的弟子列表
    • 提供弟子购买订阅权限的功能
    • 发布对应任务后通知有订阅权限的弟子
  • 接受任务通知的弟子们

上面宗门任务大殿与弟子间的关系其实就构成了一个观察者模式。

参考

代码实现

思路

  • 创建一个Subject 类,内置添加观察者addObserver、删除观察者deleteObserver、通知观察者notifyObservers方法。
  • 创建一个Observer 类,观察者通过此类创建出来。
  • 实例化一个观察者类Subject 。
  • 实例一个或者多个观察者类Observer 。
  • 利用addObserver方法讲被观察者注册到观察者上。
  • 利用notifyObservers方法通知观被察者。

代码

// 定义观察者类
class Subject {
  constructor(){
    // 观察者集合
    this.observers = []
  }
  // 添加观察者
  addObserver(observer){
    console.log(observer, '添加了')
    this.observers.push(observer)
  }
  // 删除观察者
  deleteObserver(observer){
    console.log(observer, '删除了')
    this.observers = this.observers.filter(item => item !== observer)
  }
​
  // 通知观察者
  notifyObservers(target){
    this.observers.forEach(observer => observer.notify(target))
  }
}
​
// 定义被观察者类
class Observer{
  constructor(name){
    this.name = name
  }
  notify(target){
    console.log(`弟子${this.name},任务大殿现有${target}任务,速来领取!`)
  }
}

上面是一个我们实现的观察者模式实例,我们现在测试一下:

// 实例一个观察者
const subject = new Subject()
​
// 实例被观察者类
const lilei = new Observer('李雷')
const zhanghua = new Observer('张华')
const zhangsan = new Observer('张三')
​
// 将被观察者添加进观察者中
subject.addObserver(lilei)
subject.addObserver(zhanghua)
subject.addObserver(zhangsan)
​
// 任务大殿有任务了,通知弟子来领取 
subject.notifyObservers('打扫藏书阁')
// 弟子李雷,任务大殿现有打扫藏书阁任务,速来领取!
// 弟子张华,任务大殿现有打扫藏书阁任务,速来领取!
// 弟子张三,任务大殿现有打扫藏书阁任务,速来领取!
​
​
// 任务大殿的取消对张华的通知
subject.deleteObserver(zhanghua)
​
subject.notifyObservers('斩杀桃源镇隐藏筑基境妖兽')
// 弟子李雷,任务大殿现有斩杀桃源镇隐藏筑基境妖兽任务,速来领取!
// 弟子张三,任务大殿现有斩杀桃源镇隐藏筑基境妖兽任务,速来领取!

总结

观察者模式:

  • 观察者模式是一种**「对象行为型模式」。其定义了一种「对象间的一对多依赖关系」**,当观察目标发生状态变化,会通知所有观察者对象,使它们自动更新。

优点

  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系
  • 目标与观察者之间建立了一套触发机制

缺点

  • 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用
  • 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率

案例: Vue双向数据绑定

GitHub

https://github.com/zdongfeng/Pro-JavaScript-Design-Patterns