发布订阅模式
有三个主要角色:Publisher(发布者),Sharer(分配者),Subscriber(订阅者)。
发布订阅者模式的应用:页面间消息通信,例如Vue中的EventBus,angular中的ionic-angular模块中的Events组件来实现模块间或页面间的消息通信。
案例详解:
- 首先我们来看一个发布订阅者的详细案例,再做分解,这个案例是学校中一群学生新学期抢课为现实场景来写的,学生是订阅者,学校官网是任务调度中心,老师是发布者,学生通过官网推送的老师发布的课程做出响应,先看一下完整代码。
//定义一所学校(中间件,事件派发中心)
//主要功能包括校园网(topics),以及学生订阅消息(subscribe),老师发布课程(publish)
let School = {
type: "hunt",
topics: Object.create(null),
//添加订阅的事件,当一个对象订阅事件的时候,分别传入事件名字和回调函数(当订阅事件触发时候执行的操作)
subscribe: function (topic, fn) {
//如果派发对象内检索不到这个对象,就说明是一个新事件,新建一个数组对象,然后把该订阅者的回调放进事件对象中
//topics是一个对象,里面有多个事件对象,事件对象内部是一个数组,包含这个事件的订阅者
if (!this.topics[topic]) {
this.topics[topic] = [];
}
console.log("添加订阅" + topic + "的学生到Peter老师的订阅对象中");
this.topics[topic].push(fn);
},
//发布事件,在事件订阅对象中检索这个事件,有就调用该对象中所有回调,否则直接返回
publish: function (topic, money) {
if (!this.topics[topic]) return;
for (let fn of this.topics[topic]) {
console.log("校园网发布" + topic + "课程");
fn(money);
}
},
};
//定义一个师生类
//包括姓名,身份
function Student(name, identity) {
this.name = name;
this.identity = identity;
//师生可以在校园网上发布订阅任务
//定义一个订阅函数,这里面调用了任务中心的订阅函数,收集所有订阅者的订阅事件和回调
this.subscribe = function subscribe(topic, fn) {
console.log(
this.identity + "的" + this.name + "在校园网订阅了" + topic + "的课程"
);
School.subscribe(topic, fn);
};
//定义一个发布函数,这里面调用了任务中心的发布函数,调用所有订阅者的回调
this.publish = function publish(topic, money) {
console.log(
this.identity + "老师" + this.name + "在校园网发布了" + topic + "的课程"
);
School.publish(topic, money);
};
}
//案例开始,先定义学生,老师
let studentMing = new Student("小明", "大一");
let studentJin = new Student("小金", "大一");
let studentZhang = new Student("小张", "大一");
let studentPeter = new Student("Peter", "老师");
//小明,小金,小张分别订阅了发布课程
studentMing.subscribe("Peter老师", function (money) {
console.log("小明表示:" + (money = "美术课" ? "不" : "") + "接取美术课");
});
studentJin.subscribe("Peter老师", function (money) {
console.log("小金表示:接取任何课程");
});
studentZhang.subscribe("Peter老师", function (money) {
console.log(
"小张表示:" + (money = "前端课" ? "我不上其他课," : "") + "我要上前端课啊"
);
});
//Peter发布了课程,美术课
studentPeter.publish("Peter老师", "美术课");
运行结果:
总共分为三个步骤:
首先定义一个事件中心,这里有一个订阅对象,这里面有多个事件对象,每个事件对象中用数组包含多个订阅者,他有一个添加订阅者方法,通过事件名称,将事件订阅对象分类,并且将它们的回调放进该事件对象的订阅者数组中,当发布者发布新消息,触发另外一个发布事件方法,他会循环事件对象内部那个对应的数组,触发所有回调,通知所有订阅者。
第二步,定义观察者和发布者,观察者订阅发布者者发布的事件。
第三步,发布者发布事件。
观察者模式和发布者模式的区别
- 观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。
- 观察者模式由具体目标调度,每个别订阅的目标内都需要对观察者进行处理。
- 发布订阅者同意由调度中心处理,订阅者发布者互不干扰。