Open
Description
观察者模式(Observer Pattern)
观察者模式定义了对象间的一种一对多
的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。
发布订阅模式(Pub-Sub Pattern)
在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。
观察者模式和发布订阅模式有什么区别?
我们先来看下这两个模式的实现结构:
观察者模式: 观察者直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。
发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时, 由调度中心统一调度(Fire Event) 订阅者注册到调度中心的处理代码。
我们再来看下这两个模式的代码案例:
观察者模式:
语文、数学、英语老师都找小明帮忙干活,小明干完活后会主动通知每一位老师,这样老师就知道小明干完活了
function People () {
this.list = [];
}
People.prototype.public = function () {
this.list.forEach((item) => {
item()
})
}
People.prototype.subscribe = function (target, fn) {
target.list.push(fn);
}
const teacherChina = new People();
const teacherMath = new People();
const teacherEnglish = new People();
const studentMing = new People();
teacherChina.subscribe(studentMing, function () {
console.log("小明打印好了文件");
})
teacherMath.subscribe(studentMing, function () {
console.log("小明拿回了快递");
})
teacherEnglish.subscribe(studentMing, function () {
console.log("小明给文件盖完了章");
})
studentMing.public()
发布订阅模式:
老师把作业写在了黑板上,有同学写完了就在黑板上写上名字,当老师看黑板的时候就知道谁写完了,不用跟学生交流。
const Blackboard = {
topics: {},
subscribe: function (topic, fn) {
if (!this.topics[topic]) {
this.topics[topic] = [];
}
this.topics[topic].push(fn);
},
publish: function (topic) {
this.topics[topic] && this.topics[topic].forEach((item) => {
item();
})
}
}
function People () {
this.list = [];
}
People.prototype.subscribe = function (topic, fn) {
Blackboard.subscribe(topic, fn)
}
People.prototype.publish = function (topic) {
Blackboard.publish(topic);
}
const teacherChina = new People();
const teacherMath = new People();
const teacherEnglish = new People();
const student1 = new People();
const student2 = new People();
const student3 = new People();
teacherChina.subscribe("finshed_china_work", function () {
console.log("有学生完成了语文作业");
})
teacherMath.subscribe("finshed_math_work", function () {
console.log("有学生完成了数学作业");
})
teacherEnglish.subscribe("finshed_english_work", function () {
console.log("有学生完成了英语作业");
})
student1.publish("finshed_china_work");
student2.publish("finshed_math_work");
student3.publish("finshed_english_work");
观察者模式和发布订阅模式具体的写法和区别没有官方的定义,下面这种写法反而更常见。
手写一个EventBus
function EventBus () {
this.map = {};
}
EventBus.prototype.on = function(type, handle){
this.map[type] = (this.map[type] || []).concat(handle);
}
EventBus.prototype.off = function(type, handle){
if(this.map[type]){
if(handle){
const index = this.map[type].indexof(handle);
this.map[type].splice(index, 1);
}else{
delete this.map[type];
}
}
}
EventBus.prototype.fire = function(type, data){
this.map && this.map[type].forEach(handle => handle(data));
}
测试代码
const eventBus = new EventBus()
eventBus.on('click:btn', data => {
console.log(data)
})
eventBus.fire('click:btn', {a: 1, b: 2})
eventBus.off('click:btn')
eventBus.fire('click:btn', {a: 1, b: 2})