迭代器模式

要解决的问题

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

实现原理

基本所有语言都实现了迭代器,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. python引用py文件中文报错

    文件 a.py 中引用文件 b.py 如果文件b.py中包含中文,会报错. 文件hello.py中代码如下: def say_nihao(): print "你好" 文件main. ...

  2. Hive:常用的一些命令

    1.一般可以通过beeline,代理方式登录hive; 2.使用数据库abc_hive_db:use abc_hive_db; 3.查看数据库中有哪些表:show tables :有哪些特定表 sho ...

  3. ZooKeeper的Znode剖析

    在ZooKeeper中,节点也称为znode.由于对于程序员来说,对zk的操作主要是对znode的操作,因此,有必要对znode进行深入的了解. ZooKeeper采用了类似文件系统的的数据模型,其节 ...

  4. REq,RES编码设置

    import java.io.IOException; import javax.servlet.Filter;import javax.servlet.FilterChain;import java ...

  5. android手机和ios手机的分辨率

    Android手机目前常见的分辨率 1.1 手机常见分辨率: 4:3 VGA     640*480 (Video Graphics Array) QVGA  320*240 (Quarter VGA ...

  6. 优化 bulk insert

    https://www.simple-talk.com/sql/learn-sql-server/bulk-inserts-via-tsql-in-sql-server/

  7. Ubuntu+Apache2+Mono+MVC3

    1.安装ssh(上传文件用,也可以用FTP) sudo apt-get install openssh-server 2.安装Apache2 apahe2:sudo apt-get install a ...

  8. javaScript中定义类或对象的五种方式

    第一种方式: 工厂方法 能创建并返回特定类型的对象的工厂函数(factory function). function createCar(sColor){ var oTempCar = new Obj ...

  9. 基于spring和Quartz定时器

    最近做一个小项目,要每7天去调用webservice获取一次数据.所以就用定时器来完成spring是4.1.6,quartz是2.2.1. 首先配置spring的xml文件.首先定义你要被执行的类 & ...

  10. Xstream解析XML

    <oschina> <catalog>1</catalog> <newsCount>0</newsCount> <pagesize&g ...