观察者模式和发布订阅模式的区别

观察者模式(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 对象在被通知之后只能执行同一个特定的更新方法,而在发布订阅模式中则可以基于不同的主题去执行不同的自定义事件。相对而言,发布订阅模式比观察者模式要更加灵活多变。

关系图

关系图

---- 本文结束,感谢您的阅读 ----