迭代器模式

要解决的问题

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

实现原理

基本所有语言都实现了迭代器,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. STMFD 和LDMFD指令

    http://blog.163.com/oy_mcu/blog/static/16864297220120193458892/ LDM/STM指令主要用于现场保护,数据复制,参数传送等. STMFD指 ...

  2. C语言数据类型取值范围

    一.获取数据类型在系统中的位数 在不同的系统中,数据类型的字节数(bytes)不同,位数(bits)也有所不同,那么对应的取值范围也就有了很大的不同,那我们怎么知道你当前的系统中C语言的某个数据类型的 ...

  3. GPS部标平台的架构设计(九)-GPS监控客户端设计

    交通部的部标过检,所有的测试都是从客户端发起的,也是在客户端体现的,在客户端承载了部标标准所要求的所有的功能,是整个部标平台当中工作量最大的部分,也是最繁琐的部分. 客户端设计面临两个问题: 1.基于 ...

  4. Python异步通信模块asyncore

    https://docs.python.org/2/library/asyncore.html This module provides the basic infrastructure for wr ...

  5. word自定义格式 并下载

    /** * * @param pRun * @param 20 间距 * @param fontSize 字体大小 * @param bold 是否加粗 * @param underLine 是否下划 ...

  6. 基础编程-java之股神

    买了一支股票,他知道从他买股票的那天开始,股票会有以下变化:第一天不变,以后涨一天,跌一天,涨两天,跌一天,涨三天,跌一天...依此类推. 为方便计算,假设每次涨和跌皆为1,股票初始单价也为1,请计算 ...

  7. C# Linq 交集、并集、差集、去重

    using System.Linq;         List<string> ListA = new List<string>(); List<string> L ...

  8. 夺命雷公狗-----React---16--事件操作事件

    <!DOCTYPE> <html> <head> <meta charset="utf-8"> <title></ ...

  9. Material Design Lite,简洁惊艳的前端工具箱。

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .网站上有对应每一 ...

  10. 关于区域性网站CMS的一些个人看法

    最近了解了几款国外开源CMS,与现有国内客户需求及业务习惯,结论如下:1.国人的习惯,有后台管理和会员管理2种,而老外大部分开源系统都是一个管理即前台管理,而且大部分架构是固定死的,如果在想抽出一个后 ...