# 发布订阅模式
发布订阅的核心: 每次event. emit(发布),就会触发一次event. on(注册)
let fs = require('fs');
let school = {}
let event = { // 订阅和发布没有明显的关联,arr是它们的纽带
arr: [],
on(fn) {
this.arr.push(fn); // 将函数依次存储到数组中
},
emit() {
this.arr.forEach(fn => fn()); // 将数组中的函数统一执行
}
}
event.on(function () {
if (Object. keys(school).length === 2) {
console.log(school)
}
})
event.on(function () {
console.log('读取了一个')
})
fs.readFile('. /name. txt', 'utf8', function (err, data) {
school.name = data;
event.emit();
});
fs.readFile('. /age. txt', 'utf8', function (err, data) {
school.age = data;
event.emit();
});
# 观察者模式
观察者模式(基于发布订阅模式) 有观察者,也有被观察者
观察者需要放到被观察者中,被观察者的状态变化需要通知观察者 我变化了 内部也是基于发布订阅模式,收集观察者,状态变化后要主动通知观察者
class Subject { // 被观察者 学生
constructor(name) {
this.state = '开心的'
this.observers = []; // 存储所有的观察者
}
// 收集所有的观察者
attach(o){ // Subject. prototype. attch
this.observers.push(o)
}
// 更新被观察者 状态的方法
setState(newState) {
this.state = newState; // 更新状态
// this 指被观察者 学生
this.observers.forEach(o => o.update(this)) // 通知观察者 更新它们的状态
}
}
class Observer{ // 观察者 父母和老师
constructor(name) {
this.name = name
}
update(student) {
console.log('当前' + this.name + '被通知了', '当前学生的状态是' + student.state)
}
}
let student = new Subject('学生');
let parent = new Observer('父母');
let teacher = new Observer('老师');
// 被观察者存储观察者的前提,需要先接纳观察者
student. attach(parent);
student. attach(teacher);
student. setState('被欺负了')
# 发布订阅模式的与观察者模式的区别
从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。