写点什么

为什么说:被观察者是 push 数据,迭代者是 pull 数据?

作者:掘金安东尼
  • 2022 年 8 月 21 日
    广东
  • 本文字数:1824 字

    阅读完需:约 6 分钟

为什么说:被观察者是 push 数据,迭代者是 pull 数据?

看到标题,xdm 可能有点懵?没关系,看完本篇,就会有种豁然开朗的感觉~


这里的 被观察者 指的是:Observer Pattern(观察者模式)中的被观察对象;


迭代者 这指的是:Iterator Pattern(迭代器模式)中的迭代对象;


没错,接下来,将分别解析这两种模式,冲 ( ̄︶ ̄)↗

被观察者

观察者模式,我们总是常见:


function clickHandler(event) {    console.log('user click!');} 
document.body.addEventListener('click', clickHandler)
复制代码


以上代码中,被观察者是 document.body,它主动注册了一个监听方法来监听点击事件,一旦发生点击,就把 event 信息带给 clickHandler 方法,然后执行;这便是观察者模式~


除了用原生 api addEventListener,其实我们也可以自己写一个更加解耦的监听方法:


class Subject { // 被观察者对象
constructor() { this.listeners = []; } addListener(listener) { // 加入监听 if(typeof listener === 'function') { this.listeners.push(listener) } else { throw new Error('listener 必須是 function') } } removeListener(listener) { // 移除监听 this.listeners.splice(this.listeners.indexOf(listener), 1) } notify(message) { // 发送通知 this.listeners.forEach(listener => { listener(message); }) } }
复制代码


构建实例:


var sub = new Subject(); // new 一个 ob 实例
function listener1(message) { console.log(message + 'from listener1'); }
function listener2(message) { console.log(message + 'from listener2');
}
sub.addListener(listener1); // 加监听1
sub.addListener(listener2); // 加监听2
sub.notify('I push a commit ') // push 信息给监听器1、2
复制代码


每当 notify 执行,sub 都会推送信息给 listener1listener2


被观察者会主动 push 信息(或者称为数据)给多个观察它的对象(监听器),就是典型的观察者模式。


题外说一句:很多 xd 会把【观察者模式】和【发布订阅模式】弄混,这里特意说明一下,二者区别在于:


  1. 观察者模式只需要 2 个角色便可成型,即 观察者 和 被观察者 ,其中 被观察者 是重点。

  2. 而发布订阅需要至少 3 个角色来组成,包括 发布者 、 订阅者 和 发布订阅中心 ,其中 发布订阅中心 是重点。

迭代者

JS Iterator(迭代器)我们也并不陌生,它在 ES6 被提出:


示例代码如下:


var arr = [1, 2, 3];
var iterator = arr[Symbol.iterator]();
iterator.next();// { value: 1, done: false }
iterator.next();// { value: 2, done: false }
iterator.next();// { value: 3, done: false }
iterator.next();// { value: undefined, done: true }
复制代码


Iterator 最大的魅力在于 延迟计算,关于这点,在本瓜以前的文章可以找到一些相关讨论:


你觉得“惰性求值”在 JS 中会怎么实现?


听君一席话,如听一席话,解释解释“惰性求值”~


举个栗子🌰


function* getNumbers(words) {    for (let word of words) {      if (/^[0-9]+$/.test(word)) {          yield parseInt(word, 10);      }    }}
const iterator = getNumbers('今天是 3 月 8 号');
iterator.next();// { value: 3, done: false }iterator.next();// { value: 8, done: false }iterator.next();// { value: undefined, done: true }
复制代码


getNumbers 方法用于获取字符串里面的数字,当我们执行 iterator = getNumbers('今天是 3 月 8 号') 这一句代码时,程序并没有开始计算,直到我们逐个执行 iterator.next() 才会逐个得到运算结果。这就是延迟计算。


Iterator 就像是在 pull 数据,运行一次 .next() 就拉取一次数据;

小结

OK,结合以上代码,我们分析了 “为什么说:被观察者是 push 数据,迭代者是 pull 数据?”


一图胜千言:



不过说到底,我们为什么要把这两种设计模式单拎出来作这样解释呢?


噢,其实是为了理解 RxJS Observable,它是二者思想的结合;


它大致长这样:


var observable = Rx.Observable     .create(function(observer) {     observer.next('Jerry'); // RxJS 4.x 以前的版本用 onNext     observer.next('Anna'); })
复制代码


我们后面再来逐渐揭开它的面纱~~ 这里只用先理解其背景思想,有个大致概念和印象即可;


我是掘金安东尼,输出暴露输入,技术洞见生活,再会啦~~

发布于: 刚刚阅读数: 3
用户头像

安东尼陪你度过漫长编程岁月~ 2022.07.14 加入

社会我瓜哥,人狠话不多😎 微信 anthony1453,加我交个朋友😎 正联合【机械工业出版社】出版《程序员成长手册》,敬请期待😎 真正的大师,永远怀着一颗学徒的心(易)😎

评论

发布
暂无评论
为什么说:被观察者是 push 数据,迭代者是 pull 数据?_前端_掘金安东尼_InfoQ写作社区