前言

前段时间接了个外包赚了点小钱钱,就没有怎么更新博客,最近有时间了,继续更新博客。

概念

观察者模式定义了对象间的一种一对多的依赖关系,当对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新,观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯

发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在

好了好了,知道这上面描述的很官方,看下文吧

观察者模式

观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯

观察者模式就像是,CUIT(驾校)某一天我是说某一天,从双流一变成了双一流学校,那么所有学生的学历都从重本(驾校) -> 双一流
,那么CUIT(目标者)和所有的学生之间(观察者)就构成了一种一对多的依赖关系,这种关系也称为观察者模式

模式特征

  1. 一个目标者对象 Subject,拥有方法:添加 / 删除 / 通知 Observer;
  2. 多个观察者对象 Observer,拥有方法:接收 Subject 状态变更通知并处理;
  3. 目标对象 Subject 状态变更时,通知所有 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
class CUIT {
constructor() {
this.students = []
}
addStudent(student) {
this.students.push(student)
}
removeStudent(student) {
this.students = this.students.filter((item) => item !== student)
}
notify() {
this.students.forEach((student) => {
student.update()
})
}
}

class Student {
constructor(name) {
this.name = name
}
update() {
console.log(this.name + '的学历从驾校变成了双一流')
}
}

const cuit = new CUIT()
const student1 = new Student('张三')
const student2 = new Student('李四')


cuit.addStudent(student1)
cuit.addStudent(student2)
cuit.notify()
// > "张三的学历从驾校变成了双一流"
// > "李四的学历从驾校变成了双一流"

cuit.removeStudent(student2)
cuit.notify()
// > "张三的学历从驾校变成了双一流"

发布-订阅模式

发布-订阅模式就像是,抖音(发布者)上有很多视频,但是不是一下子将所有的视频推送给你,而是将每个视频分好所属的类型,然后根据你的个人兴趣推送给你(订阅者)该类型的视频

模式特征

1.对象间功能解耦,弱化对象间的引用关系;
2.更细粒度地管控,分发指定订阅主题通知

实例

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class PubSub {
constructor() {
this.messages = {};
this.listeners = {};
}
// 添加发布者
publish(type, content) {
const existContent = this.messages[type];
if (!existContent) {
this.messages[type] = [];
}
this.messages[type].push(content);
}
// 添加订阅者
subscribe(type, cb) {
const existListener = this.listeners[type];
if (!existListener) {
this.listeners[type] = [];
}
this.listeners[type].push(cb);
}
// 通知
notify(type) {
const messages = this.messages[type];
const subscribers = this.listeners[type] || [];
subscribers.forEach((cb, index) => cb(messages[index]));
}
}

class Publisher {
constructor(name, context) {
this.name = name;
this.context = context;
}
publish(type, content) {
this.context.publish(type, content);
}
}

class Subscriber {
constructor(name, context) {
this.name = name;
this.context = context;
}
subscribe(type, cb) {
this.context.subscribe(type, cb);
}
}

const TYPE_A = 'music';
const TYPE_B = 'movie';
const TYPE_C = 'novel';

const pubsub = new PubSub();

const publisherA = new Publisher('publisherA', pubsub);
publisherA.publish(TYPE_A, 'we are young');
publisherA.publish(TYPE_B, 'the silicon valley');
const publisherB = new Publisher('publisherB', pubsub);
publisherB.publish(TYPE_A, 'stronger');
const publisherC = new Publisher('publisherC', pubsub);
publisherC.publish(TYPE_C, 'a brief history of time');

const subscriberA = new Subscriber('subscriberA', pubsub);
subscriberA.subscribe(TYPE_A, res => {
console.log('subscriberA received', res)
});
const subscriberB = new Subscriber('subscriberB', pubsub);
subscriberB.subscribe(TYPE_C, res => {
console.log('subscriberB received', res)
});
const subscriberC = new Subscriber('subscriberC', pubsub);
subscriberC.subscribe(TYPE_B, res => {
console.log('subscriberC received', res)
});

pubsub.notify(TYPE_A);
pubsub.notify(TYPE_B);
pubsub.notify(TYPE_C);

区别

发布订阅模式更灵活,是进阶版的观察者模式,指定对应分发。

观察者模式维护单一事件对应多个依赖该事件的对象关系;
发布订阅维护多个事件(主题)及依赖各事件(主题)的对象之间的关系;
观察者模式是目标对象直接触发通知(全部通知),观察对象被迫接收通知。发布订阅模式多了个中间层(事件中心),由其去管理通知广播(只通知订阅对应事件的对象);
观察者模式对象间依赖关系较强,发布订阅模式中对象之间实现真正的解耦。

参考文献

https://vue3js.cn/interview/design/Observer%20%20Pattern.html#%E4%B8%89%E3%80%81%E5%8C%BA%E5%88%AB