发布订阅模式
发布订阅是一种设计模式,它定义了一种一对多的关系,让多个观察对象同时监听某一个主题对象,当主题对象状态发生改变时,会通知所有的观察者对象,使他们能够执行各自的操作。
核心概念
- 发布者:产生并发送消息的组件,不直接将信息发送给特定的接收者。
- 订阅者:声明对某类信息感兴趣并接收相关消息的组件。
- 消息代理:中介组件,负责接收发布者的消息并根据订阅关系将消息分发给订阅者。
- 主题:消息的分类标识,订阅者通过订阅特定主题来接收相关消息。
主要特定
- 松耦合:发布者和订阅者彼此不知道对方存在
- 异步通信:消息的发送和接收可以不同步
- 动态订阅:订阅关系可以运行时动态变更
- 一对多传播:一条消息可以被多个订阅者接收
发布订阅的代码实现
class EventEmitter{
constructor(){
this.eventList={
}
}
on(eventName,cb){
if(!this.eventList[eventName]){
this.eventList[eventName]=[]
}
this.eventList[eventName].push(cb)
}
emit(eventName){
if(this.eventList[eventName]){
const handeler=this.eventList[eventName].slice()
handeler.forEach((item)=>{
item()
})
}
}
off(eventName,cb){
const callback=this.eventList[eventName]
const index=callback.indexOf(cb)
if(index!==-1)
{
callback.splice(index,1)
}
}
once(eventName,cb){
const warp=()=>{
cb()
this.off(eventName,warp)
}
this.on(eventName,warp)
}
}
// 创建事件发射器实例
const _event = new EventEmitter();
// 定义事件处理函数
function kang() {
console.log('杨总买房子');
}
function ji() {
console.log('刘总也买房子');
}
function cheng() {
console.log('成哥买车位');
}
// 测试常规事件监听
_event.on('hasHouse', kang);
_event.on('hasHouse', ji);
// 测试一次性事件监听
_event.once('hasCar', cheng);
// 触发事件测试
console.log('--- 第一次触发 hasCar 事件 ---');
_event.emit('hasCar'); // 应该执行 cheng 函数
console.log('\n--- 第二次触发 hasCar 事件 ---');
_event.emit('hasCar'); // 不应该再执行,因为是一次性监听
console.log('\n--- 触发 hasHouse 事件 ---');
_event.emit('hasHouse'); // 应该执行 kang 和 ji 函数
// 测试取消监听
console.log('\n--- 取消 kang 的 hasHouse 监听后 ---');
_event.off('hasHouse', kang);
_event.emit('hasHouse'); // 现在应该只执行 ji 函数
}
测试结果
发布订阅模式实现思路(基于缓存列表)
- 创建缓存列表对象
- on方法(订阅事件)
- emit方法(发布事件)
- off方法(取消订阅)
- once方法(一次监听)额外功能
观察者模式
观察者模式是一种行为设计模式,它定义了一种一对多的依赖关系,当一个对象(被观察者)的状态发生改变时,所有依赖于它的对象(观察者)都会自动收到通知并执行相应更新。
发布订阅的代码实现
//1.被观察者(Subject)
class Subject{
constructor(){
this.observers=[]//存储观察者的数组
}
add(observer){
this.observers.push(observer)
}
ontify(data){
this.observers.forEach(observer=>observer(data))
}
}
// 2.使用示例
const subject=new Subject()
const observer1=(data)=>{
console.log('观察者1收到',data)
}
const observer2=(data)=>{
console.log('观察者2收到',data)
}
subject.add(observer1)
subject.add(observer2)
subject.ontify('新消息')
// 输出
// 观察者1收到 新消息
// 观察者2收到 新消息