观察者模式(Observer)
观察者模式指的是一个对象(Subject
)维持一系列依赖于它的对象(Observer
),当有关状态发生变更时 Subject
对象则通知一系列 Observer
对象进行更新。
在观察者模式中,Subject
对象拥有添加、删除和通知一系列 Observer
的方法等等,而 Observer
对象拥有更新方法等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class Subject { constructor() { this.list = []; } add(ob) { this.list.push(ob); } remove(ob) { this.list.splice(this.list.indexOf(this.list.find((item) => ob.id === item.id)), 1); } notfiy() { this.list.forEach((i) => { i.update(i.id); }); } } class Observer { constructor(id) { this.id = id; } update(id) { console.log(`我是${id},我被通知了!`); } }
let people1 = new Observer(123); let people2 = new Observer(9527); let people3 = new Observer(89757);
let sub = new Subject();
sub.add(people1); sub.add(people2); sub.add(people3);
sub.notfiy();
setTimeout(() => { sub.remove(people2); sub.notfiy(); }, 200);
|
发布订阅模式(Publisher && Subscriber)
发布订阅模式指的是希望接收通知的对象(Subscriber
)基于一个 主题
通过自定义事件订阅主题,被激活事件的对象(Publisher
)通过发布主题事件的方式通知各个订阅该主题的 Subscriber
对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class Pub { constructor() { this.list = {}; } subscribe(name, cb) { if (!this.list[name]) { this.list[name] = []; } this.list[name].push(cb); } unSubscribe(name) { this.list[name] = []; } publish(...args) { const name = Array.from(args).shift(); if (!this.list[name] || this.list[name].length === 0) { console.log(`${name}主题没有可发布的事件!`); return; } this.list[name].forEach((item) => { item(args); }); } }
let publisher = new Pub();
publisher.subscribe('event1', (e) => { console.log(e); }); publisher.subscribe('event1', (e) => { console.log(e); }); publisher.subscribe('event2', (e) => { console.log(e); }); publisher.subscribe('event3', (e) => { console.log(e); });
publisher.publish('event1', '额外参数1'); setTimeout(() => { publisher.unSubscribe('event2'); publisher.publish('event2', '额外参数2'); publisher.publish('event3', '额外参数3', '额外参数4'); }, 2000);
|
发布订阅模式是观察者模式的一种变体。发布订阅只是把一部分功能抽象成一个独立的 ChangeManager
。
在「一对多」的场景下,发布者的某次更新只想通知它的部分订阅者?
在「多对一」或者「多对多」场景下。一个订阅者依赖于多个发布者,某个发布者更新后是否需要通知订阅者?还是等所有发布者都更新完毕再通知订阅者?
这些逻辑都可以放到 ChangeManager
里。
观察者模式中依赖于 Subject
对象的一系列 Observer
对象在被通知之后只能执行同一个特定的更新方法,而在发布订阅模式中则可以基于不同的主题去执行不同的自定义事件。相对而言,发布订阅模式比观察者模式要更加灵活多变。
关系图
![关系图]()