乐趣区

关于javascript:精读设计模式-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 = state
    this.notify()}

  // 读取状态
  public getState() {return this.state}
}

// 观察者
class Observer {
  // 保护指标
  private subject: Subject

  constructor(subject: Subject) {
    this.subject = subject
    this.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 许可证)

退出移动版