如何自己搭建发布订阅模式
观察者模式
什么是观察者模式(别称:发布-订阅模式)
- 观察者模式定义了对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都将得到通知, 并自动更新。观察者模式属于行为型模式, 行为型模式关注的是对象之间的通讯, 观察者模式就是观察者和被观察者之间的通讯。
- 观察者模式有一个别名叫“发布-订阅模式”, 或者说是“订阅-发布模式”, 订阅者和订阅目标是联系在一起的, 当订阅目标发生改变时, 逐个通知订阅者。我们可以用报纸期刊的订阅来形象的说明, 当你订阅了一份报纸, 每天都会有一份最新的报纸送到你手上, 有多少人订阅报纸, 报社就会发多少份报纸, 报社和订报纸的客户就是上面文章开头所说的“一对多”的依赖关系。
发布者模式
什么是发布者模式
- 其实24种基本的设计模式中并没有发布订阅模式, 上面也说了, 他只是观察者模式的一个别称。但是经过时间的沉淀, 似乎他已经强大了起来, 已经独立于观察者模式, 成为另外一种不同的设计模式。
- 在现在的发布订阅模式中, 称为发布者的消息发送者不会将消息直接发送给订阅者, 这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件, 称为消息代理或调度中心或中间件, 它维持着发布者和订阅者之间的联系, 过滤所有发布者传入的消息并相应地分发它们给订阅者。
- 举一个例子, 你在微博上关注了A, 同时其他很多人也关注了A, 那么当A发布动态的时候, 微博就会为你们推送这条动态。A就是发布者, 你是订阅者, 微博就是调度中心, 你和A是没有直接的消息往来的, 全是通过微博来协调的(你的关注, A的发布动态)。
区别
观察者模式和发布订阅模式有什么区别?
观察者模式

发布订阅模式

- 观察者模式: 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。
- 发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
实现观察者模式:
var eventBus = {
events: {},
addEvent: function (eventKey, fun) {
if (!this.events[eventKey]) {
this.events[eventKey] = [];
}
this.events[eventKey].push(fun);
},
emitEvents: function (eventKey) {
this.events[eventKey].forEach(item=>{
item();
})
},
removeEvent: function (eventKey, fun) {
for(let i=0; i<this.events[eventKey].length; i++) {
let item = this.events[eventKey][i];
if (item == fun){
this.events[eventKey].splice(i,1);
break;
}
}
}
}
function fn() {
console.log("1");
}
function fn2() {
console.log("2");
}
eventBus.addEvent("事件1", fn)
eventBus.addEvent("事件1", fn2)
eventBus.emitEvents("事件1");
eventBus.removeEvent("事件1", fn2);
eventBus.emitEvents("事件1")
VM2514:26 1
VM2514:29 2
VM2514:26 1
实现发布订阅者模式:(两套类似写法):
------------------------写法1 start------------------------
var eventBus = {
events: {},
addEvent: function (eventKey, fun) {
if (!this.events[eventKey]) {
this.events[eventKey] = [];
}
this.events[eventKey].push(fun);
},
emitEvents: function (eventKey) {
this.events[eventKey].forEach(item=>{
item();
})
},
removeEvent: function (eventKey, fun) {
for(let i=0; i<this.events[eventKey].length; i++) {
let item = this.events[eventKey][i];
if (item == fun){
this.events[eventKey].splice(i,1);
break;
}
}
}
}
var personEvent = {
info: {age:"", name:""},
add: function (eventKey, fun) {
eventBus.addEvent(eventKey, fun);
},
emit: function (eventKey) {
eventBus.emitEvents(eventKey);
},
};
function fn() {
console.log("1");
}
function fn2() {
console.log("2");
}
personEvent.info = {age:17, name:"xiaomi"};
personEvent.add("事件1", fn)
personEvent.add("事件1", fn2)
personEvent.emit("事件1")
VM4061:36 1
VM4061:39 2
------------------------end------------------------
------------------------写法2 start------------------------
var eventBus = {
events: {},
addEvent: function (eventKey, fun) {
if (!this.events[eventKey]) {
this.events[eventKey] = [];
}
this.events[eventKey].push(fun);
},
emitEvents: function (eventKey) {
this.events[eventKey].forEach(item=>{
item();
})
},
removeEvent: function (eventKey, fun) {
for(let i=0; i<this.events[eventKey].length; i++) {
let item = this.events[eventKey][i];
if (item == fun){
this.events[eventKey].splice(i,1);
break;
}
}
}
}
function personEvent(age, name) {
this.age = age;
this.name = name;
}
personEvent.prototype.add = (eventKey, fun) => {
eventBus.addEvent(eventKey, fun);
}
personEvent.prototype.emit = (eventKey) => {
eventBus.emitEvents(eventKey);
}
function fn() {
console.log("1");
}
function fn2() {
console.log("2");
}
function fn3() {
console.log("3");
}
let _personEvent = new personEvent(17, "xiaomi");
_personEvent.add("事件1", fn);
_personEvent.add("事件1", fn2);
_personEvent.add("事件1", fn3);
_personEvent.emit("事件1");
VM3122:38 1
VM3122:41 2
VM3122:44 3
------------------------end------------------------