观察者模式
/**
* 观察者模式
* 角色: 观察者:n 目标对象:1
* 观察者可以接受目标对象发布的信息(update),然后根据信息作出对应的反应
* 目标对象可以被观察者进行订阅,或者说是目标对象新增(接纳)新的观察者 ===> addObserver
* 目标对象可以发布任务给当前的观察者队列 ===> notify
*/
// 观察者类
class Observer {
constructor(name) {
this.name = name;
}
// 获取目标对象的信息
update({ type, info }) {
console.log(type, info);
this.go(info);
}
// 观察者的动作
go(info) {
console.log(`${this.name} get ${info}`);
}
}
// 目标对象类
class Subject {
constructor() {
this.observeList = [];
}
// 新增观察者
addObserver(observe) {
this.observeList.push(observe);
}
// 发布任务
notify(task) {
this.observeList.forEach(observer => observer.update(task));
}
}
const subject = new Subject();
const observer1 = new Observer('one');
const observer2 = new Observer('two');
// 新增观察者
subject.addObserver(observer1);
subject.addObserver(observer2);
const task1 = {
type: 'testType',
info: 'testInfo'
}
subject.notify(task1);
发布订阅模式
/**
* 发布订阅者模式
* 角色: 发布者 事件中心 订阅者
* 发布者给每一种类型的任务新建一个事件处理中心 ===> 订阅方法
* 发布者可以发布不同类型的任务 ===> 发布任务
* 对应的任务类型会由对应的事件中心进行处理 ===> 订阅方法的函数参数
*/
class Subscribe {
constructor() {
// 事件中心
this.subscribeCenter = new Map();
}
// 订阅方法
addSubscribe(type, fn) {
// 如果这个类型的事件中心不存在,那就新增这个事件中心
if (!this.subscribeCenter.has(type)) {
this.subscribeCenter.set(type, []);
}
/**
* 防止重复订阅
* 允许同一类型有不同的操作(方法)
* 当操作(方法)不同时通过push新增
*/
if (!this.subscribeCenter.get(type).find(itemFn => itemFn === fn)) {
this.subscribeCenter.get(type).push(fn);
}
}
// 发布
publish(type, data) {
/**
* 判断当前类型的事件中心是否存在
* 存在获取当前事件中心的所有订阅者的操作
* 遍历当前允许的操作,发布任务
*/
if (this.subscribeCenter.has(type)) {
const fnList = this.subscribeCenter.get(type);
fnList.forEach(fn => {
fn(data);
});
}
}
/**
* 取消订阅
* 取消的是一个类型下的一个操作
*/
unsubscribe(type, fn) {
if (this.subscribeCenter.has(type)) {
const fnList = this.subscribeCenter.get(type);
if (fnList.length) {
for (let i = 0; i < fnList.length; i++) {
if (fnList[i] === fn) {
fnList.splice(i, 1);
break;
}
}
}
}
}
/**
* 取消全部订阅
* 取消的是一个类型的事件中心
*/
unsubscribeAll(type) {
if (this.subscribeCenter.has(type)) {
this.subscribeCenter.delete(type);
}
}
}
// function callback() {
// console.log(123);
// }
let subscribe = new Subscribe();
subscribe.addSubscribe('game', function (event) {
console.log(`game is ${event}`);
})
subscribe.addSubscribe('learn', function (event) {
console.log(`learn is ${event}`);
});
// 发布任务
subscribe.publish('game', "打游戏")
subscribe.publish('learn', "学习")
观察者模式与订阅发布模式原理相似,基本可以理解为相同原理下的不同写法。