观察者模式
- 什么是观察者模式
- 观察者观察到目标做了什么事情之后,观察者要做出某些反应
- vue中,data数据获取或者改变之后,通知页面相关数据重新渲染
理解1:学生听到铃声后上课或下课
说明:学生(观察者)听到铃声(被观察者)做出相应的处理(上课/下课)
理解2:房屋直租(租客与房东直接联系)老王->房东, 小明->找房人1号,小红->找房人2号
老王现在的租客还有10天左右到期不想继续租他的房子,所以老王又要重新找租客,于是在小区公告栏贴上房屋出租消息(…联系人:小王15182*****)。刚毕业的小明小明和准备进城找工作的小红恰好看到了老王的房屋出租消息,于是两人分别给老王打电话告诉老王自己有租房意愿,老王听后告诉他们房子现在还有租客,过几天租客走了才能入住,小明和小红表示可以接受,希望老王到时候能通知自己。几天后老王的租客搬走了,于是就打电话告诉小明和小红现在可以入住了。小明和小红听到消息后第二天就办理了入住。
说明:
1.老王就是被观察者
2.老王贴的出租信息,是为了有租客能联系他
3.小明和小红打电话给老王(attch添加观察者的方法,告诉老王自己要租房)
4.老王原来的租客走了(setState房屋变成空的,可以通知notify新人入住)
5.小明和小红接到老王的电话,第二天入住(update)
- 简单实现观察者模式
实现思路:被观察者的行为变化了就通知观察者进行更新做出响应处理
1.观察者如何知道被观察者行为发生了变化?
在被观察者身上绑定观察者名单
2.如何在被观察者身上绑定观察者名单?
被观察者身上有一个添加观察者的方法
3.如何触发添加观察者的方法?
在实例化观察者时需要将被观察者实例传递过去,通过调用被观察的方法传递过去
4.观察者何时做出更新响应处理?
被观察者行为改变则通知观察者进行更新
//被观察者
class subject{
constructor(){
this.state="上课啦"
this.observers=[]//观察者名单
}
setState(state){
this.state=state
this.notify()//通知观察者更新
}
getState(){
return this.state
}
attch(observer){//添加观察者的方法
this.observers.push(observer)
}
notify(){
this.observers.forEach(item=>{
item.update()//观察者执行更新操作
})
}
}
//观察者
class Observer{
constructor(name,subject){
this.name=name
this.subject=subject//报错被观察者信息
this.subject.attch(this)//将观察者自己添加到观察者名单中,等待被通知
}
update(){//观察者收到消息后的更新方法
console.log(`${this.name}--${this.subject.getState()}`)
}
}
//测试 小明o1和小红o2都是学生(观察者),听到铃声s1(被观察者)上下课
let s1=new subject()
let o1=new Observer("小明",s1)
let o2=new Observer("小红",s1)
s1.setState("上课啦")//上课铃声响起
//小明--上课啦
//小红--上课啦
setTimeout(() => {
s1.setState("下课啦")//下课铃声响起
}, 2000);
//小明--下课啦
//小红--下课啦
发布订阅(中央事件)
- 什么是发布订阅
- 发布订阅是观察者设计模式的延伸,发布订阅不是设计模式,只是一种设计思路。
- javaScript中的addEventListener就是一种发布订阅
function handler1(){
console.log('handler1执行了')
}
function handler2(){
console.log('handler2执行了')
}
function handler3(){
console.log('handler3执行了')
}
btn.addEventListener('click', handler1, false)
btn.addEventListener('click', handler2, false)
btn.addEventListener('click', handler3, false)
//观察click事件是否触发,如果触发了,就执行对应的回调函数
理解:想象公众号订阅流程(订阅了才会给你推送相关消息)
某一天,小明听小红说“XXX公众号”的文章写得可好看了…小明听了感觉还不错,于是小明也在微信上关注(订阅)了“XXX公众号”(在你关注时,微信记录了你想看的公众号名称,以及你的联系方式)。第二天你关注的公众号在微信上发布了新文章,微信收到新文章,就在订阅者名单上找到谁订阅了次公众号,并通过他们的联系方式将最新的文章推送过去。小明也就在微信上收到了这篇新文章。后来某一天小明觉得这公众号的文章没有以前的好看了,于是取消关注“XXX公众号”(此时微信将你之前的订阅信息删除了),当公众号再发新文章时,微信就不会将他的文章推送给你。
说明:在订阅公众号的过程中,微信就这个中间人(经纪人Bus),时刻关注着谁订阅了某个消息,谁发布了某个消息,谁又取消订阅了某个消息
- 简单实现发布订阅模式
<script>
class Bus{
constructor(){
this.catch={}
}
on(name,fn){
if(this.catch[name]){
this.catch[name].push(fn)
}else{
this.catch[name]=[fn]
}
}
off(name,fn){
let tasks=this.catch[name]
if(tasks){
let index=tasks.findIndex(f=>f===fn || f.callback===fn)
if(index>=0){
this.catch[name].splice(index,1)
}
}
}
emit(name,once=false,...args){
if(this.catch[name]){
this.catch[name].forEach(fn=>{
fn(...args)
})
}
if(once){
delete this.catch[name]
}
}
}
// 测试
let bus = new Bus()
function fn1(data) {
console.log("我是fn1", data)
}
function fn2(data) {
console.log("我是fn2", data)
}
bus.on("test", fn1)
bus.on("test", fn2)
bus.emit("test", false, "这是第一次触发")
bus.off("test",fn1)
bus.emit("test", false, "这是第二次触发")
</script>
观察者模式和发布订阅模式区别
- 观察者模式只有观察者和被观察者
- 发布订阅模式有发布者,订阅者和经纪人
- 发布订阅模式可以看做的观察者模式的升级,进步一降低了观察者和被观察者的耦合度
- 理解:没有中介的租房(房东和租房者直接联系);有中介的租房(房东和租客的信息都是在中介这,中介作为房东和租客沟通的桥梁)