观察者模式和发布订阅模式的区别
理解观察者模式和发布订阅模式的定义、实现和使用场景
问题
观察者模式和发布订阅模式分别是什么?它们有什么区别?
解答
观察者模式
观察者模式中,观察者直接订阅主题对象。当主题状态改变时,会直接通知所有观察者。
// 主题(被观察者)
class Subject {
constructor() {
this.observers = [];
}
// 添加观察者
addObserver(observer) {
this.observers.push(observer);
}
// 移除观察者
removeObserver(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
}
// 通知所有观察者
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
// 观察者
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} 收到更新:`, data);
}
}
// 使用
const subject = new Subject();
const observer1 = new Observer('观察者1');
const observer2 = new Observer('观察者2');
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify('状态改变了');
发布订阅模式
发布订阅模式中,发布者和订阅者不直接通信,而是通过调度中心(事件中心)进行解耦。
// 调度中心(事件中心)
class EventBus {
constructor() {
this.events = {};
}
// 订阅事件
subscribe(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = [];
}
this.events[eventName].push(callback);
}
// 发布事件
publish(eventName, data) {
if (this.events[eventName]) {
this.events[eventName].forEach(callback => callback(data));
}
}
// 取消订阅
unsubscribe(eventName, callback) {
if (this.events[eventName]) {
this.events[eventName] = this.events[eventName].filter(cb => cb !== callback);
}
}
}
// 使用
const eventBus = new EventBus();
// 订阅者1
eventBus.subscribe('userLogin', (data) => {
console.log('订阅者1 收到登录事件:', data);
});
// 订阅者2
eventBus.subscribe('userLogin', (data) => {
console.log('订阅者2 收到登录事件:', data);
});
// 发布者发布事件
eventBus.publish('userLogin', { username: 'Alice' });
主要区别
角色数量不同:观察者模式只有观察者和被观察者两个角色,它们直接通信。发布订阅模式有发布者、订阅者和调度中心三个角色,发布者和订阅者通过调度中心间接通信。
耦合程度不同:观察者模式中,主题和观察者相互知道对方的存在,耦合度较高。发布订阅模式中,发布者和订阅者完全解耦,互不知道对方的存在。
使用场景不同:观察者模式适合单个应用内部使用,比如 Vue 的响应式系统。发布订阅模式适合跨应用或跨模块的场景,比如 Node.js 的 EventEmitter、浏览器的事件系统。
关键点
- 观察者模式是主题直接通知观察者,两者直接耦合
- 发布订阅模式通过调度中心解耦发布者和订阅者
- 观察者模式适合应用内部,发布订阅模式适合跨应用场景
- 发布订阅模式更灵活,但增加了系统复杂度
目录