「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。
正文
一、观察者模式的含义
由图可知,观察者模式分为两个角色,一个观察者一个被观察者,他们之间存在着某种联系,被观察者和观察者都可以是任意事物,观察者模式只要观察者和被观察者满足一定的条件,就可以被称为观察者模式,观察者模式是站在被观察者的角度,每个符合观察者模式的被观察者是唯一的,但任意事物都可以充当被观察者,具体什么意思我们继续往下看:
二、观察者模式的作用
观察者模式主要解决一对多信息通信问题,那什么叫一对多,又什么是通信问题,由于是站在被观察者的角度,所以出现了一对多的情况,每个观察者模式下,被观察者是唯一的,而观察者可以为多个,而通信问题,就是被观察者和观察者之间的联系,接下来具体了解:
三、观察者模式的流程
3.1 观察者模式具体解决什么问题
在编码过程中,经常会遇到,当一个数据变化时,其他数据也需要发生变化的情况,在不使用框架的情况下,原生js很难解决这个问题,举个简单的例子:
当你动态生成一些元素的时候,而这元素存放在一个数组中,随时可能添加或删减,当你将这个数组的数据渲染到页面后,这个数组发生了变化,你怎么让页面跟随数组实时更新呢? 那你可能会想到再次调用渲染函数,将新的数据渲染到页面上,但是一个问题,你什么时候调用这个渲染函数呢, 又或者说,你怎么判断数组会在时候发生变化呢? 那你可能又会想到可能使用定时器,在一段时间后调用一次函数,或者一段时间判断数组是否发生变化,是一个方法,但是如果长时间不发生变化,那么这个定时器一直在做无用功,消耗浏览器性能,所以为了解决这个问题,出现了观察者模式,
3.2 举例
问题: 被观察者看作一个商店,观察者则是顾客,假设商店要新出一个商品,顾客都想要这个商品,但是商品上架的时间不明,那顾客(观察者)需要怎么做,只能过一段时间去商店一趟,看看上货没有,只能不断去查看是否上货,非常消耗精力把 ,计算机也一样,不断访问,一直做无用功,所以有一个解决方法:
解决方法: 相信这里有很多人已经知道该怎么做了,对没错,就是让商店主动通知这些需要新商品的客户,也就是让被观察者主动通知观察者,这样观察者就不需要一遍又一遍的去检查被观察者的变化了,说到这思路是不是一下就打开了。这就是观察者模式
3.3 观察者模式的结构 --- 被观察者
那么想让被观察者主动通知观察者需要几个步骤呢
3.3.1 收集观察者
只有你知道谁需要商品,才知道该通知谁,所以先收集有哪些顾客需要这东西,也就是建立联系,但是对于代码来说,收集的数据需要有存放的位置,所以首先我们需要创建一个存放用户数据的数组
observerList = []
3.3.2 添加观察者
有了存放观察者信息的数组,那么我们就可以将观察者的信息,(用于通信的方式),存放到数组中去,
addObserver(observer) {
this.observerList.push(observer)
}
3.3.3 通知观察者
等到商品上架,也就是数据发生变化时,通知用户(观察者),
notifyObservers() {
this.observerList.forEach(item => {
item.notify(this.str)
})
}
这样就可以完成被观察者变化时主动通知观察者,被观察者必须具备, 一个存放观察者的数组, 一个添加观察者的方法, 一个通知观察者的方法
3.4 观察者模式的具体流程 --- 观察者
有了被观察者当然需要有一个或多个的观察者,不然一个人也就不需要通知谁了
3.4.1 接收被观察者的通知
notify(str) {
console.log(str + ',' + this.name + "收到");
}
被观察者通知观察者,当然观察者要有一个能接收到被观察者通知的方法,
只要存在两个角色,并且满足观察者和被观察者的要求的,这么一个集合就可以被称为观察者模式,所以现在明白为什么是一对多,为什么是站在被观察者的角度了吧,
PS: 这里大家可以创建两个类,或对象... 去模拟观察者模式的观察者和被观察者,当被观察者变化时,观察者跟随变化,这里我使用的js,可以使用ts接口的方式更加方便易懂,
//观察者
class Observer {
constructor(name) {
this.name = name
}
notify(str) {
console.log(str + ',' + this.name + "收到");
}
}
//被观察者
class Subject {
str = '2021.11.12数据更新'
observerList = []
addObserver(observer) {
this.observerList.push(observer)
}
notifyObservers() {
this.observerList.forEach(item => {
item.notify(this.str)
})
}
}
function testObserver() {
const subject = new Subject()
const person = new Observer('orange')
const person2 = new Observer('orange2')
subject.addObserver(person)
subject.addObserver(person2)
console.log(subject.observerList);
subject.notifyObservers()
}
testObserver()