观察者(Observer)模式是针对回调模式的另外一种扩展。它允许被观察者(Subject,第一个例子中的AClass实例)添加多个观察者。
因此,在被观察者中需要维护一个观察者列表(ObserverList),当数据发生变化时,需要通知所有的观察者。
举例:原型链方式
let Subject = function() {this.observers = [];}Subject.prototype.addObserver = function(obv) {this.observers.push(obv);}Subject.prototype.removeObserver = function(obv) {let index = -1;for(let i = 0; i < this.observers.length; i++) {if(this.observers[i] === obv) {index = i;break;}}if(index > 0) this.observers.splice(index, 1);}Subject.prototype.notify = function(event) {for(let obv of this.observers) {obv.update(event)}}let Observer = function() { }Observer.prototype.update = function(event) {console.log(event)}
举例:面向对象方式
class Subject {constructor() {this.observers = [];}addObserver(obv) {this.observers.push(obv);}removeObserver(obv) {let index = -1;for(let i = 0; i < this.observers.length; i++) {if(this.observers[i] === obv) {index = i;break;}}if(index > 0) this.observers.splice(index, 1);}notify(event) {for(let obv of this.observers) {obv.update(event)}}}class Observer {constructor() { }update(event) {console.log(event)}}
在业务逻辑中,通过继承的方式去实现观察者的回调逻辑和被观察者的通知逻辑:
举例:原型链方式
let AClass = function() {};AClass.prototype = new Subject();AClass.prototype.constructor = AClass;AClass.prototype.add = function(number) {this.notify("added " + number);};let BClass = function() {};BClass.prototype = new Observer();BClass.prototype.constructor = BClass;// 这种方式进行原型链重载后无法调用父类属性同名函数let a = new AClass();let b = new BClass();a.addObserver(b);a.add(5);// added 5
举例:面向对象方式
class AClass extends Subject {constructor() {super();}add(number) {super.notify("added " + number);}}class BClass extends Observer {constructor() {super();}}class CClass extends Observer {constructor() {super();}update(event) {super.update(event)console.log("SubClass " + event)}}let a = new AClass();let b = new BClass();let c = new CClass();a.addObserver(b);a.addObserver(c);a.add(5);// added 5// added 5// SubClass added 5
