观察者(Observer)模式是针对回调模式的另外一种扩展。它允许被观察者(Subject,第一个例子中的AClass实例)添加多个观察者。

因此,在被观察者中需要维护一个观察者列表(ObserverList),当数据发生变化时,需要通知所有的观察者。

举例:原型链方式

  1. let Subject = function() {
  2. this.observers = [];
  3. }
  4. Subject.prototype.addObserver = function(obv) {
  5. this.observers.push(obv);
  6. }
  7. Subject.prototype.removeObserver = function(obv) {
  8. let index = -1;
  9. for(let i = 0; i < this.observers.length; i++) {
  10. if(this.observers[i] === obv) {
  11. index = i;
  12. break;
  13. }
  14. }
  15. if(index > 0) this.observers.splice(index, 1);
  16. }
  17. Subject.prototype.notify = function(event) {
  18. for(let obv of this.observers) {
  19. obv.update(event)
  20. }
  21. }
  22. let Observer = function() { }
  23. Observer.prototype.update = function(event) {
  24. console.log(event)
  25. }

举例:面向对象方式

  1. class Subject {
  2. constructor() {
  3. this.observers = [];
  4. }
  5. addObserver(obv) {
  6. this.observers.push(obv);
  7. }
  8. removeObserver(obv) {
  9. let index = -1;
  10. for(let i = 0; i < this.observers.length; i++) {
  11. if(this.observers[i] === obv) {
  12. index = i;
  13. break;
  14. }
  15. }
  16. if(index > 0) this.observers.splice(index, 1);
  17. }
  18. notify(event) {
  19. for(let obv of this.observers) {
  20. obv.update(event)
  21. }
  22. }
  23. }
  24. class Observer {
  25. constructor() { }
  26. update(event) {
  27. console.log(event)
  28. }
  29. }

在业务逻辑中,通过继承的方式去实现观察者的回调逻辑和被观察者的通知逻辑:

举例:原型链方式

  1. let AClass = function() {};
  2. AClass.prototype = new Subject();
  3. AClass.prototype.constructor = AClass;
  4. AClass.prototype.add = function(number) {
  5. this.notify("added " + number);
  6. };
  7. let BClass = function() {};
  8. BClass.prototype = new Observer();
  9. BClass.prototype.constructor = BClass;
  10. // 这种方式进行原型链重载后无法调用父类属性同名函数
  11. let a = new AClass();
  12. let b = new BClass();
  13. a.addObserver(b);
  14. a.add(5);
  15. // added 5

举例:面向对象方式

  1. class AClass extends Subject {
  2. constructor() {
  3. super();
  4. }
  5. add(number) {
  6. super.notify("added " + number);
  7. }
  8. }
  9. class BClass extends Observer {
  10. constructor() {
  11. super();
  12. }
  13. }
  14. class CClass extends Observer {
  15. constructor() {
  16. super();
  17. }
  18. update(event) {
  19. super.update(event)
  20. console.log("SubClass " + event)
  21. }
  22. }
  23. let a = new AClass();
  24. let b = new BClass();
  25. let c = new CClass();
  26. a.addObserver(b);
  27. a.addObserver(c);
  28. a.add(5);
  29. // added 5
  30. // added 5
  31. // SubClass added 5