什么是观察者模式
我们往往会出现这种需求:当一个对象的行为发生改变时,他的改变会影响到其他对象,使得那些对象相应的做出改变。
那么这个改变的对象我们称之为观察目标,而那些被影响到的对象我们称之为观察者
举个最常见的栗子
当我们需要给某个DOM监听鼠标的点击事件,但我们并不知道用户什么时候点击,需要提前添加相应的事件与点击事件绑定。这个时候点击事件便是观察目标,我们绑定的自定义事件便是观察者。
const box = document.querySelector('.box');
box.addEventListener('click', ()=>{
console.log('box clicked one');
})
box.addEventListener('click', ()=>{
console.log('box clicked two');
})
如上简单的代码我们便为box这个DOM加入了两个观察者。
如何自己实现一个观察者模式
这里我们以微信公众号和用户为案例
// 微信公众号
class WeChat {
constructor(account){
this.account = account
this.observer = new Set()
}
addObserver(ob){
this.observer.add(ob)
}
removeObserver(ob){
this.observer.delete(ob)
}
pushArticles(content){
this.observer.forEach(ob=>{
ob.readArticles(this.account,content)
})
}
}
// 微信用户
class Person {
constructor(user){
this.user = user
}
readArticles(article,content){
console.log(`${this.user}: ${content}, from ${article}`)
}
}
// 创建公众号
const account_1 = new WeChat('solo的自我修养')
// 创建微信用户
const user_1 = new Person('nini')
const user_2 = new Person('guapi')
// 加入用户
account_1.addObserver(user_1)
account_1.addObserver(user_2)
// 推送文章
account_1.pushArticles('you are good man')
account_1.removeObserver(user_1)
account_1.pushArticles("don't say something")
总结:
- 观察目标要存入所有观察者。
- 观察者写入监听时执行的方法。
- 在触发观察目标监听事件方法时,遍历所有观察者并执行观察者所需执行的相应方法。
什么是发布订阅模式
大多数文章都提到发布订阅模式是观察者模式的别称。虽然说他们两者确实大相径庭,但在编程思想上还是有其不同之处。
就上面的案例我们用发布订阅模式写会是怎样的呢?
// 公众号作者
class WeChatAuthor {
constructor(author){
this.author = author
}
writeArticles(admin,article){
admin.pushArticle(article)
}
}
// 微信用户
class Person {
constructor(user){
this.user = user
}
readArticles(article,wechat){
console.log(`${this.user}用户读了来自 ${wechat}公众号的文章: ${article}`)
}
}
// 公众号
class WeChatAdmins {
constructor(wechat){
this.wechat = wechat
this.persons = new Set()
}
addPerson(person){
this.persons.add(person)
}
removePerson(person){
this.persons.delete(person)
}
pushArticle(article){
this.persons.forEach(person => {
person.readArticles(article,this.wechat)
})
}
}
// 申请成为公众号作者
const author = new WeChatAuthor('我要暑假')
// 建立公众号
const wechat = new WeChatAdmins('前端暑假旅游度假区')
// 微信用户
const person_1 = new Person('尤雨河')
const person_2 = new Person('尤雨江')
// 关注'前端暑假旅游度假区'公众号
wechat.addPerson(person_1)
wechat.addPerson(person_2)
// 作者通过'前端暑假旅游度假区'公众号发布文章
author.writeArticles(wechat,'Vue3顶呱呱!')
// 输出结果:
// 尤雨河用户读了来自 前端暑假旅游度假区公众号的文章: Vue3顶呱呱!
// 尤雨江用户读了来自 前端暑假旅游度假区公众号的文章: Vue3顶呱呱!
观察者模式 vs 发布订阅模式
前面我们用两种模式书写了同一个功能案例可以发现两个的不同点。我这里用人话来描述,大家可以细品下区别:
- 观察者模式:
作者在公众号写文章->公众号推送给所有关注的读者 - 发布订阅模式:
作者写好文章->把文章复制粘贴到相应的公众号上->公众号推送给所有关注的读者
区别总结:发布订阅模式是将观察目标和观察者进行解耦,创建调度中心的功能中间层。观察者不再与观察目标有直接关联,观察者只需观察调度中心,而观察目标的改变也只需通知调度中心。