Skip to content

观察者设计模式 / Observer

Example & Code

javascript
class ObserverList {
  constructor() {
    this.list = [];
  }
  add(obj) {
    this.list.push(obj);
  }
  indexOf(obj, startIndex = 0) {
    let i = startIndex;
    while (i < this.list.length) {
      if (this.list[i] === obj) {
        return i;
      }
      i++;
    }
    return -1;
  }
  removeAt(index) {
    this.list.splice(index, 1);
  }
  count() {
    return this.list.length;
  }
  get(index) {
    return this.list[index];
  }
}

class Subject {
  constructor() {
    this.observers = new ObserverList();
  }
  addObserver(observer) {
    this.observers.add(observer);
  }
  removeObserver(observer) {
    this.observers.removeAt(this.observers.indexOf(observer));
  }
  notify(value) {
    const count = this.observers.count();
    for (let i = 0; i < count; i++) {
      this.observers.get(i).update(value);
    }
  }
}

class Observer {
  constructor() {}
  update(value) {}
}

class ConcreteSubject extends Subject {
  constructor(element) {
    super();
    this.element = element;
    this.element.onclick = () => {
      this.notify(this.element.checked);
    };
  }
}

class ConcreteObserver extends Observer {
  constructor(element) {
    super();
    this.element = element;
  }
  update(value) {
    this.element.checked = value;
  }
}
// Demo
const addBtn = document.getElementById('addNewObserver');
const container = document.getElementById('observerContainer');
const controlCheckbox = new ConcreteSubject(document.getElementById('mainCheckbox'));

const addNewObserver = () => {
  const check = document.createElement('input');
  check.type = 'checkbox';
  const checkObserver = new ConcreteObserver(check);
  controlCheckbox.addObserver(checkObserver);
  container.appendChild(check);
};
addBtn.addEventListener('click', addNewObserver);