观察者模式
观察者模式就好个体奶农(Subject)和个人(Observers)的关系;奶农负责统计有多少人订了产品(Subscribe),个人都会有一个相同拿牛奶的方法(Event);奶农有新奶了就负责调用这个方法(Fire Event)。
观察者模式是一对多的关系,多个观察者对应一个对象;当被观察对象更新时会通知所有观察者。
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
|
// 观察者
class Observer {
constructor(name) {
this.name = name;
this.fn = null;
}
update() {
console.log(`我是${this.name},听说被观察者更新了...`);
typeof this.fn === 'function' && this.fn();
}
}
// 被观察对象
class Subject {
list = []; // 保存所有观察者
addObserver(observer) {
// 添加新增的观察者
this.list.push(observer);
}
notifyObservers() {
// 通知观察者,我更新了
this.list.forEach(item => {
item.update();
});
}
}
let subject = new Subject();
let zhangsan = new Observer('张三');
let lisi = new Observer('李四');
let wangwu = new Observer('王五');
zhangsan.fn = () => {
console.log('哈哈');
};
lisi.fn = () => {
console.log('呵呵');
};
wangwu.fn = () => {
console.log('嗨嗨');
};
// 添加订阅
subject.addObserver(zhangsan);
subject.addObserver(lisi);
subject.addObserver(wangwu);
// 通知更新
subject.notifyObservers();
|
发布订阅模式
发布订阅模式就好像报社(Publishers)、邮局(Topic/Event Channel)和个人(Subscribers)的关系;报纸的订阅(Subscribe)和分发(Fire Event)是由邮局来完成的,报社只负责将报纸发送给邮局(Publish Topic/Event)。
发布订阅模式是多对多的关系,可以有多个发布者多个观察者;每个发布者对应着多个观察者,每个观察者对应着多个发布者。
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
|
class Subscriber {
constructor(name) {
this.name = name;
this.fn = null;
}
subscribe(channel) {
channel.addSubscriber(this.name, this);
}
update() {
console.log(`我是${this.name},我的快递到了...`);
typeof this.fn === 'function' && this.fn();
}
}
class Publisher {
constructor(type) {
this.type = type;
}
publishTopic(channel) {
channel.notifySubscribers(this.type);
}
}
class Channel {
list = {};
addSubscriber(type, subscriber) {
let list = this.list[type] || [];
list.push(subscriber);
this.list[type] = list;
}
notifySubscribers(type) {
this.list[type].forEach(item => {
item.update();
});
}
}
let channel = new Channel();
let zhangsan = new Subscriber('张三');
let lisi = new Subscriber('李四');
let wangwu = new Publisher('王五');
let zhaoliu = new Publisher('赵六');
zhangsan.subscribe(channel);
lisi.subscribe(channel);
wangwu.publishTopic(channel);
zhaoliu.publishTopic(channel);
|
回归 Vue
对于响应式对象,Vue 会在对象属性的 getter 中收集属性对应的依赖,在对象属性的 setter 中通知对应依赖进行更新;一个数据对象对应多个依赖,数据是被观察目标,视图、计算属性、侦听器这些是观察者/依赖者。
参考