一个典型的观察者模式应用场景是用户在一个网站订阅主题
多个用户(观察者,Observer)都可以订阅某个主题(Subject),当主题内容更新时订阅该主题的用户都能收到通知
Subject是构造函数,new Subject() 创建一个主题对象,该对象内部维护订阅当前主题的观察者数组。主题对象上有一些方法,如添加观察者(addObserver)、删除观察者(removeObserver)、通知观察者更新(notify)。 当notify 时实际上调用全部观察者 observer 自身的 update 方法。
Observer 是构造函数,new Observer() 创建一个观察者对象,该对象有一个 update 方法。
class Subject { constructor() { this.observers = [] } addObserver(observer) { this.observers.push(observer) } removeObserver(observer) { this.observers = this.observers.filter(o !== observer) } notify() { this.observers.forEach(observer => observer.update()) } } class Observer{ constructor() { this.update = function() {} } } let subject = new Subject() let observer1 = new Observer() observer1.update = function() { console.log('observer1 update') } subject.addObserver(observer1) let observer2 = new Observer('valley') observer2.update = function() { console.log('observer2 update') } subject.addObserver(observer2) subject.notify()
上面的代码中,主题被观察者订阅的写法是 subject.addObserver(observer), 不是很直观,给观察者增加订阅方法
class Observer{ constructor() { this.update = function() {} } subscribeTo(subject) { subject.addObserver(this) } } let subject = new Subject() let observer = new Observer() observer.update = function() { console.log('observer update') } observer.subscribeTo(subject) //观察者订阅主题 subject.notify()
const EventManager = (function(){ let eventList = {} function on(event, handler) { if(!eventList[event]) { eventList[event] = [handler] }else { eventList[event].push(handler) } } function fire(event, data) { if(eventList[event]) { eventList[event].forEach(handler => handler(data)) } } function off(event, handler) { if(eventList[event]) { if(!handler) { delete eventList[event] }else { let index = eventList[event].indexOf(handler) eventList[event].splice(index, 1) } } } return { on: on, fire: fire, off: off } })() EventManager.on('sayHello', function(data) { console.log('hello ' + data) }) EventManager.fire('sayHello', 'jirengu')