什么是观察者模式
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
日常的使用:EventHandler vs EventListener
我们先来复习一下基础知识。
大家都知道,大多数时间里面,FE都是面向浏览器编程的,即基于DOM脚本的编程环境来工作。
在开发过程中,用户与浏览器的交互是少不了的,所以我们必须基于「事件驱动」去做一些事情。
最简单的例子,绑定一个button
元素的点击事件:
当然,我们更多希望点击事件是在js代码中方便维护。so:
好,那上面我们做的事情,就是给button
附加了一个「事件处理器」(Eventhandler)来监听点击事件。
那么,如果我再往上加一个事件处理函数呢?
那么最后我点击按钮,执行了什么?
被暴击了!
为啥没有执行”被猛击了”呢?因为事件处理器对于一种特定的事件类型,最多只能注册一个程序。上面的例子中,fn2把fn1覆盖掉了。
那么我希望顺序执行fn1和fn2怎么办?当然就是使用addEventListener这种「事件监听器」(EventListener)方法拉。
点击之:
被猛击了!
被暴击了!
好,那我们来看,在这个过程中,EventListener
这个事件监听器做了哪些事情:
- 监听了
click
事件,并附加了2个处理函数。说明一个事件可对应多个监听函数。
- 当用户点击时,顺序执行这2个函数。
- fn1和fn2之间是没有联系的。我也可以很方便地再加个fn3。
实际上,EventListener就是一个浏览器内部实现的观察者模式
:
- 一个对象发生改变(用户点击)时,通知其他对象(执行监听函数)。
- 发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者。
- 这些观察者之间没有相互联系,可以根据需要增加和删除观察者(removeEventListener),使得系统更易于扩展。
OK,我们已经看到了观察者模式
的使用,那么下面我们来实现观察者模式。
观察者模式的实现:PM2.5
最近帝都的PM2.5几乎天天爆表,在各大应用市场中,PM2.5实时指数的APP下载量也一路飙升。
如果PM2.5指数高于200就算是重度污染,所以,产品狗打算开发个功能,用户可以通过APP的某个设置开关来订阅是否发送空气污染的预警提醒。
那么空气污染指数多高算高呢?有些用户认为300以上是高,有些用户认为100就很高了。
那么,这个值交由用户来设置。
如果用户订阅之后,用户希望当高于用户的设置值时,用户手机就会触发一个预警提醒,提醒出门好戴口罩。
下面我们来做一个具体的实现。
首先是我们的观察者,这里就可以认为是服务器
; 服务器上存储了订阅用户的信息,并有通知用户的功能。当然,还具有获取并设置PM2.5的功能。
好,下面我们来实现用户类User
。用户的关键方法是analyze
, 即比对当前空气污染指数和设定值。同时用户有个唯一标识符id
。
好,现在我们来做一个具体的调用:
例子可以运行得很好。
上面的例子中可以看出:
- 用户在例子中即是「观察者」,服务器为「观察对象」;
- 「服务器」和「用户」是一个一对多的关系;可以根据需要增加或删除用户
- 当服务器的空气污染指数改变时,会实时通知用户,用户去执行自身的更新方法(例子中为
analyze
,大多数写法会写成update
)。
- 用户彼此之间是没有关系的。
回到事件监听器
现在让我们回到事件监听器。
再次分析,我们可以认为,fn1和fn2都是观察者,而dom的点击事件是被观察对象。
如果点击了,那么就执行fn1和fn2。这里的部分伪代码如下:
总结
观察者模式的优点如下:
- 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
- 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
- 观察者模式支持「事件广播」。
- 观察者模式符合“开闭原则”的要求。
是否明白呢亲?
以上。