[发布订阅和观察模式都是一种行为型设计模式,用来实现对象之间的一对多的通知机制。它们的区别主要有以下几点 1 2 3 4 5 6 7
- 观察者模式中,观察者和被观察者是直接交互的,观察者需要订阅被观察者的事件,并且被观察者需要维护一个观察者列表,当事件发生时,被观察者会遍历这个列表并通知每个观察者。这样就导致了观察者和被观察者之间存在一定的耦合性,如果被观察者发生变化,可能会影响到所有的观察者。
- 发布订阅模式中,发布者和订阅者之间没有直接联系,而是通过一个第三方的调度中心来进行消息的传递。发布者只需要将消息发送给调度中心,订阅者只需要从调度中心订阅感兴趣的消息,当消息到达时,调度中心会负责将消息分发给对应的订阅者。这样就实现了发布者和订阅者之间的解耦,它们不需要知道对方的存在。
- 观察者模式更多地用于单个应用内部的对象间通信,而发布订阅模式更多地用于跨应用或跨系统的消息传递
简易发布订阅模式
function EventEmitter() {
this._events = {};
}
EventEmitter.prototype.on = function (evetName, fn) {
//订阅
this._events[evetName] = this._events[evetName] || [];
this._events[evetName].push(fn);
};
EventEmitter.prototype.emit = function (evetName, args) {
//触发发布
this._events[evetName].forEach((fn) => {
fn(args);
});
};
EventEmitter.prototype.off = function (evetName, fn) {
//解除订阅
this._events[evetName] = this._events[evetName].filter((item) => {
return item != fn && item.fn != fn;
});
};
EventEmitter.prototype.once = function (evetName, fn) {
//只订阅一次,触发就解除订阅
let once = (...args) => {
fn(args);
this.off(evetName, once);
};
once.fn = fn;
this.on(evetName, once);
};
const eventEmitter1 = new EventEmitter();
const handle1 = (name) => {
console.log("hello" + name);
};
const handle2 = (name) => {
console.log("goodbye" + name);
};
const handle3 = (name) => {
console.log("juest one time:" + name);
};
eventEmitter1.on("handle1", handle1);
eventEmitter1.on("handle1", handle2);
eventEmitter1.emit("handle1", "joker");
console.log('---------------');
eventEmitter1.once("handle1", handle3);
eventEmitter1.off("handle1", handle2);
eventEmitter1.emit("handle1", "joker");
console.log('---------------');
eventEmitter1.emit("handle1", "joker");
观察者有耦合关系,但是订阅者不关心接受信息的人拿信息去做什么,两者是解耦的
简易观察者模式模式
class Subject {
deps: Array<Observer>
state: Number
constructor() {
this.deps = []
this.state = 0
}
attach(obs: Observer): void {
this.deps.push(obs)
}
setState(state: number) {
this.state = state
this.notifyAll()
}
notifyAll(): void {
this.deps.forEach((item: Observer) => {
item.run(this.state)
})
}
}
abstract class Observer {
subject: Subject
constructor(subject: Subject) {
this.subject = subject
console.log(this);
this.subject.attach(this)
}
abstract run(data: Number | String): void
}
class BinaryObserver extends Observer {
constructor(subject: Subject) {
super(subject)
}
run() {
console.log('this is BinaryObserver');
}
}
class ArrayObserver extends Observer {
constructor(subject: Subject) {
super(subject)
}
run() {
console.log('this is ArrayObserver');
}
}
const subject = new Subject()
const obj1 = new BinaryObserver(subject)
const obj2 = new ArrayObserver(subject)
subject.setState(2)