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)

弊端

不要拘泥于实现形式,比如上面代码中的例子,subjectobserver1observer2 是一对多的关系,但不一定非要用这种代码组织形式来实现观察者效果。我们也可以利用 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 观察者模式》相关推荐

  1. 【韩松】Deep Gradient Comression_一只神秘的大金毛_新浪博客

    <Deep Gradient Compression> 作者韩松,清华电子系本科,Stanford PhD,深鉴科技联合创始人.主要的研究方向是,神经网络模型压缩以及硬件架构加速. 论文链 ...

  2. 【韩松】Deep Gradient Comression

    <Deep Gradient Compression> 作者韩松,清华电子系本科,Stanford PhD,深鉴科技联合创始人.主要的研究方向是,神经网络模型压缩以及硬件架构加速. 论文链 ...

  3. [文献阅读] 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 ...

  4. 【翻译】Batch Normalization: Accelerating Deep Network Trainingby Reducing Internal Covariate Shift

    Batch Normalization: Accelerating Deep Network Trainingby Reducing Internal Covariate Shift Sergey I ...

  5. 模型加速--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 ...

  6. 论文笔记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 提出了特征 ...

  7. 端到端图像压缩《Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation》

    Asymmetric Gained Deep Image Compression With Continuous Rate Adaptation 一 简介 二 内容 2.1 目前方法的缺陷 2.2 整 ...

  8. 深度学习视频压缩1—DVC: An End-to-end Deep Video Compression Framework

    本文是第一篇端到端使用神经网络来进行视频压缩的论文, github地址:GitHub - GuoLusjtu/DVC: DVC: An End-to-end Deep Video Compressio ...

  9. 【论文阅读】Deep Compositional Captioning: Describing Novel Object Categories without Paired Training Data

    [论文阅读]Deep Compositional Captioning: Describing Novel Object Categories without Paired Training Data ...

  10. CVPR 2018 TRACA:《Context-aware Deep Feature Compression for High-speed Visual Tracking》论文笔记

    理解出错之处望不吝指正. 本文的模型叫做TRACA.模型中使用多个expert auto-encoder,在预训练阶段,每个expert auto-encoder针对一个特定类进行训练:在tracki ...

最新文章

  1. php 为啥报错,php Soap 报错 求大神帮忙看看为什么
  2. Go学习笔记—锁(sync包)
  3. 为什么我切换到React Native来创建超级简单的底页
  4. python安装成功的图标_安装Python
  5. 【白皮书分享】2021中国女性婚恋观白皮书.pdf(附下载链接)
  6. VScode输出中文乱码的解决方法------测试过可以用
  7. 第1章 iFIX概述
  8. Java面试题目(非通用模板)
  9. 把计算机网络关闭啦怎么打开,网络发现已关闭怎么办?Win7系统启用/关闭网络发现方法(图文)...
  10. .NET利用ActionFilter特性记录日志或者运行性能计数器。(log trace or perform perfcounter by actionFilter attribute)...
  11. multsim 函数发生器的使用
  12. Java操作外部数据源(RDBMS,Hive,HBase)
  13. 图形外部加文字 r语言_将外部图形卡连接到笔记本电脑的最佳方法
  14. 怎么在电脑上用计算机,如何把旧电脑变成云电脑?戳这里
  15. Qt 5.12 编写多窗口程序(新手手把手教学)
  16. 密码学——elgama加解密及数字签名算法
  17. web服务验证事件合法请求,使用到了__VIEWSTATE、__EVENTVALIDATION、cookie来验证
  18. 代码随想录训练营day36
  19. SPSS Chi-Square
  20. android性能优化的相关视频资料

热门文章

  1. Python-OpenCV图像处理(二):模糊操作
  2. 基于MFC框架的学生信息管理系统/学生成绩管理系统(带有图形化界面)
  3. 什么是海外调查问卷?都有哪些形式
  4. UC/OS II 任务管理(4)之任务创建
  5. 【计算机网络】利用WireShark分析TCP/UDP协议
  6. 通过rvm 安装 ruby
  7. 安全测试值得学习的工具有哪些?
  8. drill apache_使用Apache Drill对混合模式数据进行SQL查询
  9. mvcmvpmvvm
  10. go 日志库zap的使用