精读《设计模式 - Observer 观察者模式》
Observer(观察者模式)
Observer(观察者模式)属于行为型模式。
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
拿项目的 npm 依赖举例子:npm 包与项目是一对多的关系(一个 npm 包被多个项目使用),当 npm 包发布新版本时,如果所有依赖于它的项目都能得到通知,并自动更新这个包的版本号,那么就解决了包版本更新的问题,这就是观察者模式要解决的基本问题。
举例子
如果看不懂上面的意图介绍,没有关系,设计模式需要在日常工作里用起来,结合例子可以加深你的理解,下面我准备了三个例子,让你体会什么场景下会用到这种设计模式。
对象与视图双向绑定
在 精读《设计模式 - Proxy 代理模式》 中我们也提到了双向绑定概念,只不过代理是实现双向绑定的一个具体方案,而观察者模式才是在描述双向绑定这个概念。
观察者模式在最初提出的时候,就举了数据与 UI 相互绑定的例子。即同一份数据可以同时渲染为表格与柱状图,那么当操作表格更新数据时,如何让柱状图的数据也刷新?从这个场景引出了对观察者模式的定义,即 “数据” 与 “UI” 是一对多的关系,我们需要一种设计模式实现当 “数据” 变化时,所有依赖于它的 “UI” 都得到通知并自动更新。
拍卖
拍卖由一个拍卖员与多为拍卖者组成。拍卖时,由 A 同学喊出的竞价(我出 100)就是观察者向目标发出的 setState
同时,此时拍卖员喊出(有人出价 100,还有更高的吗?)就是一个 notify
通知行为,拍卖员通知了现场竞价全员,刷新了他们对当前最高价的信息。
聊天室
聊天室由一个中央服务器与多个客户端组成。客户端发送消息后,就是向中央服务器发送了 setState
更新请求,此时中央服务器通知所有处于同一聊天室的客户端,更新他们的信息,从而完成一次消息的发送。
意图解释
数据与 UI 的例子已经详细说明了其意图含义,这里就不赘述了。
结构图
Subject: 目标,即例子中的 “数据”。
Observer: 观察者,即例子中的 “表格”、“柱状图”。
还是以数据与 UI 同步为例,当表格发生操作修改数据时,表格这个 TableObserver 会调用 Subject(数据)的 setState
,此时数据被更新了。然后数据这个 Subject
维护了所有监听(包括表格 TableObserver
与柱状图 ColumnChartObserver
),此时 setState
内会调用 notify
遍历所有监听,并依次调用 Update
方法,每个监听的 Update
方法都会调用 getState
获取最新数据,从而实现表格更新后 -> 更新数据 -> 表格、柱状图同时刷新。
为了更好的理解,以这张协作图为例:
aConcreteSubject
: 对应例子中的数据。aConcreteObserver
: 对应例子中的表格。anotherConcreteObserver
: 对应例子中的柱状图。
代码例子
下面例子使用 typescript 编写。
PS: 为了简化处理,就不定义 Subject 接口与 ConcreteSubject 了,而是直接用 Subject 类代替。Observer 也同理。
// 目标,管理所有观察者
class Subject {// 观察者数组private observers: Observer[] = []// 状态private state: State// 通知所有观察者private notify() {this.observers.forEach(eachObserver => {eachObserver.update()})}// 新增观察者public addObserver(observer: Observer) {this.observers.push(observer)}// 更新状态public setState(state: State) {this.state = statethis.notify()}// 读取状态public getState() {return this.state}
}// 观察者
class Observer {// 维护目标private subject: Subjectconstructor(subject: Subject) {this.subject = subjectthis.subject.addObserver(this)}// 更新public update() {// 比如渲染表格 or 渲染柱状图console.log(this.subject.getState())}
}// 客户端调用
const subject = new Subject()
// 创建观察者
const observer1 = new Observer(subject)
const observer2 = new Observer(subject)
// 更新状态
subject.setState(10)
弊端
不要拘泥于实现形式,比如上面代码中的例子,subject
与 observer1
、observer2
是一对多的关系,但不一定非要用这种代码组织形式来实现观察者效果。我们也可以利用 Proxy 很轻松的实现:
const obj = new Proxy(obj, {get(target,key) {}set(target,key,value) {}
})renderTable(obj)
renderChart(obj)
我们可以在 obj
被任意一个组件访问时触发 get
,进而对 UI 与视图进行绑定;被任意一个组件更新时触发 set
,进而对所有使用到的视图进行刷新。使用设计模式切记不要死板,理解原理就行了,在不同平台有不同的更加优雅的实现方式。
总结
观察者模式是非常常用的设计模式,它描述了对象一对多依赖关系下,如何通知并更新的机制,这种机制可以用在前端的 UI 与数据映射、后端的请求与控制器映射,平台间的消息通知等大部分场景,无论现实还是程序中,存在依赖且需要通知的场景非常普遍。
讨论地址是:精读《设计模式 - Observer 观察者模式》· Issue #302 · dt-fe/weekly
如果你想参与讨论,请 点击这里,每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。
关注 前端精读微信公众号
版权声明:自由转载-非商用-非衍生-保持署名(创意共享 3.0 许可证)
精读《设计模式 - Observer 观察者模式》相关推荐
- 【韩松】Deep Gradient Comression_一只神秘的大金毛_新浪博客
<Deep Gradient Compression> 作者韩松,清华电子系本科,Stanford PhD,深鉴科技联合创始人.主要的研究方向是,神经网络模型压缩以及硬件架构加速. 论文链 ...
- 【韩松】Deep Gradient Comression
<Deep Gradient Compression> 作者韩松,清华电子系本科,Stanford PhD,深鉴科技联合创始人.主要的研究方向是,神经网络模型压缩以及硬件架构加速. 论文链 ...
- [文献阅读] Sparsity in Deep Learning: Pruning and growth for efficient inference and training in NN
文章目录 1. 前言 2. Overview of Sparsity in Deep Learning 2.1 Generalization 2.2 performance and model sto ...
- 【翻译】Batch Normalization: Accelerating Deep Network Trainingby Reducing Internal Covariate Shift
Batch Normalization: Accelerating Deep Network Trainingby Reducing Internal Covariate Shift Sergey I ...
- 模型加速--CLIP-Q: Deep Network Compression Learning by In-Parallel Pruning-Quantization
CLIP-Q: Deep Network Compression Learning by In-Parallel Pruning-Quantization CVPR2018 http://www.sf ...
- 论文笔记30 -- (视频压缩)【CVPR2021】FVC: A New Framework towards Deep Video Compression in Feature Space
<FVC: A New Framework towards Deep Video Compression in Feature Space> CVPR 2021 的一篇Oral 提出了特征 ...
- 端到端图像压缩《Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation》
Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation 一 简介 二 内容 2.1 目前方法的缺陷 2.2 整 ...
- 深度学习视频压缩1—DVC: An End-to-end Deep Video Compression Framework
本文是第一篇端到端使用神经网络来进行视频压缩的论文, github地址:GitHub - GuoLusjtu/DVC: DVC: An End-to-end Deep Video Compressio ...
- 【论文阅读】Deep Compositional Captioning: Describing Novel Object Categories without Paired Training Data
[论文阅读]Deep Compositional Captioning: Describing Novel Object Categories without Paired Training Data ...
- CVPR 2018 TRACA:《Context-aware Deep Feature Compression for High-speed Visual Tracking》论文笔记
理解出错之处望不吝指正. 本文的模型叫做TRACA.模型中使用多个expert auto-encoder,在预训练阶段,每个expert auto-encoder针对一个特定类进行训练:在tracki ...
最新文章
- php 为啥报错,php Soap 报错 求大神帮忙看看为什么
- Go学习笔记—锁(sync包)
- 为什么我切换到React Native来创建超级简单的底页
- python安装成功的图标_安装Python
- 【白皮书分享】2021中国女性婚恋观白皮书.pdf(附下载链接)
- VScode输出中文乱码的解决方法------测试过可以用
- 第1章 iFIX概述
- Java面试题目(非通用模板)
- 把计算机网络关闭啦怎么打开,网络发现已关闭怎么办?Win7系统启用/关闭网络发现方法(图文)...
- .NET利用ActionFilter特性记录日志或者运行性能计数器。(log trace or perform perfcounter by actionFilter attribute)...
- multsim 函数发生器的使用
- Java操作外部数据源(RDBMS,Hive,HBase)
- 图形外部加文字 r语言_将外部图形卡连接到笔记本电脑的最佳方法
- 怎么在电脑上用计算机,如何把旧电脑变成云电脑?戳这里
- Qt 5.12 编写多窗口程序(新手手把手教学)
- 密码学——elgama加解密及数字签名算法
- web服务验证事件合法请求,使用到了__VIEWSTATE、__EVENTVALIDATION、cookie来验证
- 代码随想录训练营day36
- SPSS Chi-Square
- android性能优化的相关视频资料