extend implements多个对象_设计模式之观察者模式,努力为了对象间的解耦

638de8711909e88200007c3b73a56edb.png
很多我们所熟知的前端框架、模块都用到了观察者模式,如redux、mvvm(比如:vue)、promise、nodeJs的Event模块。它让我们的代码更加耦合,更灵活。

首先:

观察者模式 = 出版者 + 订阅者。

概念上来讲:

观察者模式,定义了出版者(Subject)和订阅者(Observer)间一对多的依赖关系。可以灵活为一个出版者(Subject)添加订阅者(Observer),移除订阅者(Observer)。当出版者状态改变时,可以通知到所有的订阅者,触发订阅者的更新。

观察者模式的大概过程是这样的。

1、【订阅者】注册对【出版者】的订阅;

2、【出版者】根据业务需求,出版者对自身的状态改变。

3、当【出版者】状态改变时,通知触发所有【订阅者】的更新。

4、如果有需要【订阅者】可以移除对【出版者】的订阅。移除成功后,就不会再被通知了

1a2c6e9563f69692a32850f0de0659bd.png

设计原则上,观察者封装了可能变法的部分(订阅者的数目和类型),并将可能变法的部分 和 固定不变(出版者)的部分分离,做到了封装变化的原则。

【订阅者】注册对【出版者】的订阅,就让【订阅者】组合进【出版者】中,做到了多用组合,少用继承的原则

从服务端语言上来讲(如Java),要实现【出版者】触发通知不同类型的【订阅者】的更新,【订阅者】implements 了同样的接口,做到了面向接口编程的原则。

应用上来讲:

拿redux来讲,就是store和components之间的关系。

大概过程如下:

1、组件通过this.unSubscribe = store.subscribe(this.handleUpdate),添加对store的订阅。

2、业务通过store.dispatch(action)触发reducer对store状态的改变。

3、store状态变化时,遍历store内部的listeners,并执行。其实就是执行(1)中的this.handleUpdate。

4、组件注销时,执行this.unSubscribe()移除组件对store的订阅。

演示下部分redux和 react-redux的源码吧。主要演示connect(mapStateToProps, mapDispatchToProps)(Component),中connet这个高级组件如何添加订阅、移除订阅,以及redux中dispatch(action)后的一系列过程

注:一下代码适合对redux有一定了解的同学(不一定要看过源码)

以下代码自react-redux/createConnet.js

handleChange

以下代码自redux/createStore.js

export 

拿mvvm(比如vue)来讲,data和dom更新的关系。

大概过程如下(涉及到模板解析的原理这边没有深入)。多了模板解析,所以加了步骤0

0、利用Object.defineProperty实现对数据属性get和set的代理。

1、模板解析时,遇到{{ name }},调用data.name,代理到Object.defineProperty的get,get时添加队【name发布者】的订阅,watch.addSub(update)。

2、根据业务data.name可能会改变。

3、data.name改变时,代理到Object.defineProperty的set,在set时遍历name属性添加的订阅,并执行,其实是就是执行(1)中的update

大概源码如下:

// updater更新其,

拿promise来讲就是,内部callbacks和then传递的函数间的关系。

promise的原理、nodeJs Event模块的原理就不再多演示了....

....

实现一个观察者模式吧

相信看完上面的案例,你自身对于如何实现一个观察者模式也有了一定的概念,就前端而言,少去了对象类型的问题(当然如果需要,我们可以引入typescript),我们改要实现的是这样的结构(就不贴代码了):

function 

说一下实际开发中的应用吧

比如用canvas画报表,由于canvas本身是一个整体,因此,我们在做一些canvas交互时(比如鼠标经过高亮显示),就需要重绘canvas,如果整块重绘的话势必对性能比较浪费。

因此,通常我会采用分层(多canvas)的处理方式,用同一份数据画多个canvas图形。将需要交互的元素画在最顶层的canvas上,去做交互时重绘最顶层的canvas的操作。

从设计思维上来考虑,可以为每个canvas的绘制创建一个订阅者,添加对“数据”(把“数据”当成出版者)的订阅。

这样多个canvas间就非常耦合,如果添加其他层的canvas时,不会对现有代码造成任何影响

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值