迭代器模式

要解决的问题

迭代器要解决的问题很简单很单纯,就是进行遍历操作。

实现原理

基本所有语言都实现了迭代器,javascript也不例外,如Array.prototype.forEachfor..of..for..in..for

迭代器的种类分两种,内部迭代器,外部迭代器。

内部迭代器

内部迭代器的迭代过程对外部是不可控的,内部自己实现迭代过程.比如forEach, jQuery中的$.each

外部迭代器

外部迭代器就相对灵活,可以控制迭代过程,需要显式调用迭代操作.外部迭代器较内部迭代器来说更方便扩展。

外部迭代器的一个实现

    // itObj 是被迭代对象,需要包含length属性
var Iterator = function(itObj) {
this.obj = itObj
this.currentItem = 0
this.length = itObj.length
} Iterator.prototype.next = function() {
if (this.currentItem < this.length) {
this.currentItem++
}
} Iterator.prototype.getCurrentItem = function() {
return this.obj[this.currentItem]
} Iterator.prototype.isDone = function() {
return this.currentItem >= this.length
} var it = new Iterator([1, 2, 3])
console.log(it.getCurrentItem()) // 1
it.next()
console.log(it.getCurrentItem()) // 2
it.next()
console.log(it.getCurrentItem()) // 3
it.next()
console.log(it.getCurrentItem()) // 3

扩展我们的迭代器,实现两个数组的merge函数

    //两个迭代器
var it1 = new Iterator([1,3,4,6])
var it2 = new Iterator([2,3,5,7]) var merge = function(it1, it2) {
var tmp = []
// 两个迭代器同时遍历
while(!it1.isDone() && !it2.isDone()) {
if (it1.getCurrentItem() > it2.getCurrentItem()) {
tmp.push(it2.getCurrentItem())
it2.next()
} else if (it1.getCurrentItem() < it2.getCurrentItem()) {
tmp.push(it1.getCurrentItem())
it1.next()
} else {
tmp.push(it1.getCurrentItem())
it1.next()
it2.next()
}
}
// 如果it1没被遍历完,直接push
while(!it1.isDone()) {
tmp.push(it1.getCurrentItem())
it1.next()
}
// 如果it2没被遍历完,直接push
while(!it2.isDone()) {
tmp.push(it2.getCurrentItem())
it2.next()
}
return tmp
} console.log(merge(it1, it2)) // [1, 2, 3, 4, 5, 6, 7]

可以看到用外部迭代器很容易地控制迭代过程,扩展功能

实践中的应用

一个copy自书上的例子

获取上传对象

未使用迭代器的版本

    var getUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload");
} catch (e) {
// IE 上传控件
if (supportFlash()) { // supportFlash 函数未提供
var str = '<object type="application/x-shockwave-flash"></object>';
return $(str).appendTo($('body'));
} else {
var str = '<input name="file" type="file"/>'; // 表单上传
return $(str).appendTo($('body'));
}
}
}

我们看到其中夹杂着try...catch语句和大量的if语句,严重违反了开闭原则。

使用迭代器重构

   var getActiveUploadObj = function() {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload"); //IE上传控件
} catch (e) {
return false;
}
};
var getFlashUploadObj = function() {
if (supportFlash()) {
var str = '<object type="application/x-shockwave-flash"></object>'
return $(str).appendTo($('body'))
}
return false
} var getFormUploadObj = function() {
var str = '<input name="file" type="file" class="ui-file" />'
return $(str).appendTo($('body'))
} var iteratorUploadObj = function() {
for (var i = 0, fn; fn = arguments[i++]) {
var uploadObj = fn()
if (uploadObj !== false) {
return uploadObj
}
}
} var uploadObj = iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj)

重构代码之后,我们可以看到,获取不同上传对象的方法被隔离在各自的函数里互不干扰, try、catch 和 if 分支不再纠缠在一起,使得我们可以很方便地的维护和扩展代码。

js设计模式总结-迭代器模式的更多相关文章

  1. js设计模式——4.迭代器模式

    js设计模式——4.迭代器模式 代码演示 /*js设计模式——迭代器模式*/ class Iterator { constructor(container) { this.list = contain ...

  2. 浅谈js设计模式之迭代器模式

    迭代器模式无非就是循环访问聚合对象中的各个元素.比如 jQuery中的 $.each 函数,其中回调函数中的参数 i 为当前索引, n 为当前元素,代码如下: $.each([1, 2, 3], fu ...

  3. JS设计模式——5.单体模式

    JS设计模式——5.单体模式 http://www.cnblogs.com/JChen666/p/3610585.html   单体模式的优势 用了这么久的单体模式,竟全然不知!用它具体有哪些好处呢? ...

  4. 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern)

    原文:乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 迭代器模式(Iterator Pattern) 作者:weba ...

  5. Python进阶:设计模式之迭代器模式

    在软件开发领域中,人们经常会用到这一个概念——“设计模式”(design pattern),它是一种针对软件设计的共性问题而提出的解决方案.在一本圣经级的书籍<设计模式:可复用面向对象软件的基础 ...

  6. 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)

    设计模式学习--迭代器模式(Iterator Pattern) 概述 ——————————————————————————————————————————————————— 迭代器模式提供一种方法顺序 ...

  7. js设计模式——7.备忘录模式

    js设计模式——7.备忘录模式 /*js设计模式——备忘录模式*/ // 备忘类 class Memento { constructor(content) { this.content = conte ...

  8. js设计模式——6.模板方法模式与职责链模式

    js设计模式——6.模板方法模式与职责链模式 职责链模式

  9. js设计模式——5.状态模式

    js设计模式——5.状态模式 代码演示 /*js设计模式——状态模式*/ // 状态(红灯,黄灯,绿灯) class State { constructor(color) { this.color = ...

随机推荐

  1. Linux服务器ftp命令找不到

    ftp commond not find 先用命令rpm -q vsftpd检查是否安装了ftp服务器 若显示vsftpd-2.2.2-11.el6_4.1.x86_64这样的信息,说明FTP服务器已 ...

  2. 拥抱基于jquery.deferred的ajax,和层层嵌套回调的ajax说拜拜

    前言 在项目中,无论是维护自己的代码,还是重构他人的项目代码,看到层层嵌套,异常冗余的某个function,那时我们的内心肯定是奔溃的! 在jquery1.5版本之前,如果我们某个操作需要多个ajax ...

  3. windows下搭建nginx+php+mysql环境

    一.下载需要的东西 1.nginx:http://nginx.org/en/download.html 2.php:http://php.net/downloads.php 3.mysql:(暂时先不 ...

  4. javascript 中的 let 作用域

    let 声明了一个块级域的局部变量,并且可以给它一个初始化值. 语法EDIT let var1 [= value1] [, var2 [= value2]] [, ..., varN [= value ...

  5. Linux Crontab 安装使用详细说明

    crontab命 令常见于Unix和Linux的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供 之后读取和执行.通常,crontab ...

  6. iframe载入页面过程显示动画效果

    http://www.xfeixiang.com/Bug/Detail/A2FD7EFFA8CA72F1

  7. lisp等

             

  8. django中文配置的问题

    language_code:'zh-hans' 生成的语言文件请使用zh_Hans,这样才能你的app和系统的app完全翻译成中文,掉此坑的请在下面留言

  9. Android Monkey测试(转载)

    Monkey是一款通过命令行来对我们APP进行测试的工具,可以运行在模拟器里或真机上.它向系统发送伪随机的用户事件流,实现对正应用程序进行压力测试. 官方介绍 :https://developer.a ...

  10. DataGrid新增行数据

    本文将介绍一下,如何通过Jquery MiniUI来添加Datagrid一行. 1.效果展示: ↓ 2.具体代码: <script type="text/javascript" ...