观察者模式(Observer Pattern)
当对象间存在一对多关系时,一个对象(observed)被修改时,则会自动通知依赖它的对象(observer)
观察者模式主要有两个主体:被观察者/目标对象(observed)、观察者(observer)
-
被观察者/目标对象(observed)
- 观察者列表(
observerList) - 通知方法
notity(自身发生变化时调用这个方法通知观察者们) - 添加观察者到列表(
addObserver)
- 观察者列表(
-
观察者(observer)实现
update方法供目标对象调用,update方法中实现自定义逻辑
// 目标对象
class Observed {
constructor() {
// 初始化观察者列表
this.observerList = []
}
// 添加观察者到列表
addObserver(observer) {
this.observerList.push(observer)
}
// 执行操作并通知依赖的观察者
notity(msg) {
this.observerList.forEach((n) => n.update(msg))
}
}
// 观察者
class Observer {
constructor(name) {
this.name = name
}
// 实现update方法
update(msg) {
console.log(`${this.name},${msg}`)
}
}
let observed = new Observed()
let observer1 = new Observer('阿坤')
let observer2 = new Observer('你干嘛~')
// 添加依赖
observed.addObserver(observer1)
observed.addObserver(observer2)
// 执行操作
observed.notity('唱,跳,rap,打篮球')
// 输出结果
阿坤,唱,跳,rap,打篮球
你干嘛~,唱,跳,rap,打篮球
发布订阅模式
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码
class EventChannel {
constructor() {
/*
事件中心其实就是一个对象,存放键值对
键就是订阅的事件
值就是一个数组包含多个事件函数
*/
this.events = {}
}
// 订阅也就是注册事件
subscribe(eventName, callback) {
if (!this.events[eventName]) {
this.events[eventName] = this.events[eventName] || []
}
this.events[eventName].push(callback)
}
// 发布方法
publish(eventName, data) {
if (this.events[eventName]) {
this.events[eventName].forEach((cb) => cb(data))
}
}
// 取消订阅
unsubscribe(eventName) {
if (this.events[eventName]) {
let newEvent = {}
for (let key in this.events) {
if (key !== eventName) {
newEvent[key] = this.events[key]
}
}
this.events = newEvent
}
}
}
// 创建调度中心
let events = new EventChannel()
/* 订阅者订阅事件比传入事件函数 */
// 订阅事件一
events.subscribe('rap', (data) => {
console.log(`${data.name}会rap`)
})
events.subscribe('rap', (data) => {
console.log(`${data.name}会rap,叽叽叽叽`)
})
// 订阅事件二
events.subscribe('singAndDance', (data) => {
console.log(`${data.name}会唱跳`)
})
// 订阅事件三
events.subscribe('playBasketball', (data) => {
console.log(`${data.name}会打篮球`)
})
/* 发布者发布事件 */
events.publish('rap', { name: '糖果超甜' })
events.publish('playBasketball', { name: '小坤脚' })
events.publish('playBasketball', { name: '啊坤' })
// 输出结果
糖果超甜会rap
糖果超甜会rap,叽叽叽叽
小坤脚会打篮球
啊坤会打篮球
总结
观察者模式是直接观察目标对象,目标对象发送通知,无论观察者是否想收到通知都会收到,而发布订阅中间多了一个调度中心,只有订阅了该事件才会收到通知
再
Vue中,数据双向绑定使用的是观察者模式,事件总线EventBus使用的是发布订阅模式
举个找房例子,
观察者模式就是我们直接面向房东,而发布订阅就类似上平台或者找中介,只有发布了我们才能看到