Observer(观察者)模式

观察者模式即,某个对象(subject)维持一系列依赖它(观察者)的对象,将有关状态的任何改变自动通知给它们。
当不再希望某个观察者获得其注册对象发出的通知时,该注册对象可以将它从观察者列表中删除

Subject(观察者容器)

  • 维护观察者,添加或删除观察者
// 容器列表,系列功能
class ObserverList {
  construcor() {
    this.list = []
  }
  Add(obj) { 
    if(this.IndexOf(obj) === -1) return this.list.push(obj)
  }
  Empty() {
    this.list = []
  }
  Count() {
    return this.list.length
  }
  Get(i) {
    if (i > -1 && i < this.list.length) {
      return this.list[i]
    }
  }
  Insert(obj, i) {
    if(this.IndexOf(obj) === -1) this.list.splice(i, 0, obj)
  }
  Remove(obj, i) {
    if (i) this.list.splice(i, 1)
    else {
      i = this.IndexOf(obj)
      this.list.splice(i, 1)
    }
  }
  IndexOf(obj) {
    return this.list.findIndex((item) => item == obj)
  }
}
// 管理观察者
class Subject {
  constructor() {
    this.observerList = new ObserverList()
  }
  AddObserver(observer) {
    this.observerList.Add(observer)
  }
  RemoveObserver(observer) {
    this.observerList.Remove(observer)
  }
  Notify(context) {
    const observersCount = this.observerList.Count()
    for (let i = 0; i < observersCount; i++) {
      this.observerList.Get(i).Update(context)
    }
  }
}
const Sub = new Subject()

Observer(观察者)

  • 具体目标发生改变时需要获得通知的对象,提供一个更新接口
class Observer {
  constructor(obj) {
    this.target = obj
    // 让容器添加当前观察者实例
    Sub.AddObserver(this)
  }
  // 通知观察者更新接口
  Update(context) {
    if(this.target) this.target.getUpdate(context)
  }
}

ConcreteSubject(具体目标)

  • 状态改变是向 Observer 发出通知,存储自身状态,实现 Observer 更新接口
  <button id='addNewObserver'>Add New Observer checkbox</button>
  <input type='checkbox' id='mainCheckbox'></input>
  <div id='observersContainer'></div>
  const controlCheckbox = document.querySelector('#mainCheckbox'),
  addBtn = document.querySelector('#addNewObserver'),
  container = document.querySelector('#observersContainer')

  addBtn['onclick'] = function() {
    // 创建新的具体目标
    const check = document.createElement('input')
    check.type = 'checkbox'
    // 创建新的观察者并添加到容器
    new Observer(check)
    // 观察者通知更新接口实现
    check.getUpdate = function(val) {
      this.checked = val
    }
    container.appendChild(check)
  }
  // 通知观察者更新
  controlCheckbox['onclick'] = function() {
    Sub.Notify(this.checked)
  }

一个栗子

给当前已存在CheckBox 1添加点击事件,通知观察者更新
点击新增按钮创建观察者并创建一个新的CheckBox,并实现观察者更新接口,接收CheckBox 1状态