// 发布订阅模式与观察者模式的不同
//1 目标对象并不直接通知观察者,而是通过事件中心来派发通知。低解耦
//2 观察者模式大多数时候是同步的,比如当事件触发,Subject 就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。
//3 发布订阅模式,不是所有订阅都必须接受消息,可以选择性通知发布者
//4 观察者模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式
Vue中的响应式是使用了观察者模式,事件机制 ($on, $emit)则使用了发布订阅模式,同时Vue 的生命周期钩子也是是利用发布订阅模式实现的,另外Vue指令使用了装饰器模式
观察者模式
//有一个消息中心,信息接受者订阅某个信息,信息发布者发布消息后,订阅这个消息的所有订阅者都能收到信息
class Subject {
constructor() {
// 消息中心
this.observers = [];
}
//订阅消息
subject(observer) {
!this.observers.includes(observer) && this.observers.push(observer);
}
//发布消息
notify() {
this.observers.forEach(function (observer) {
observer.show();
});
}
//取消消息订阅
remove(observer) {
const idx = this.observers.findIndex((item) => item === observer);
idx > -1 && this.observers.splice(idx, 1);
}
}
class Observer {
constructor(name, age) {
this.name = name;
this.age = age;
//this.ob = new Observer();
}
show() {
console.log("my name is " + this.name + " age is: " + this.age);
//console.log("发布消息了");
}
}
let sub = new Subject();
let ob1 = new Observer("zong", 22);
let ob2 = new Observer("dealdot", 32);
sub.subject(ob1);
sub.subject(ob2);
sub.notify();
发布订阅模式
class PubSub {
constructor() {
// 保存监听事件
this.event = {};
}
// 订阅
subscribe(eventName, fun) {
try {
if (!this.event.hasOwnProperty(eventName)) {
this.event[eventName] = [];
}
if (typeof fun == "function") {
this.event[eventName].push(fun);
} else {
throw new Error(`请给${eventName}事件添加回调方法`);
}
} catch (error) {
console.warn(error);
}
}
// 发布
publish(eventName, arg) {
try {
if (this.event.hasOwnProperty(eventName)) {
this.event[eventName].map((item) => {
item.call(null, arg);
});
} else {
throw new Error(`${eventName}事件未被注册`);
}
} catch (error) {
console.warn(error);
}
}
// 移除订阅
unSubscribe(eventName, fun, arg) {
try {
if (this.event.hasOwnProperty(eventName)) {
this.event[eventName].map((item, index) => {
if (item == fun) {
this.event[eventName].splice(index, 1);
item.call(null, arg);
}
});
}
} catch (error) {
console.warn(error);
}
}
}
// 实例化
const util = new PubSub();
function notice1(params) {
console.log(params);
}
function notice2(params) {
console.log(params);
}
// 订阅事件
util.subscribe("subscribe1", notice1);
util.subscribe("subscribe2", notice2);
// 发布事件
//发布者可以选择要通知的订阅者对象[与观察者模式的不同]
util.publish("subscribe1", "订阅成功");
// 移除订阅
setTimeout(() => {
util.unSubscribe("subscribe1", notice, "已取消订阅");
}, 3000);
本文由 dealdot <dealdot#163.com> 创作, Full Stack Developer @ DeepBlue
本文最后编辑时间为: Sep 9, 2021 at 14:03 pm
转载请注明来源