内容主要来自《JavaScript设计模式与开发实践》
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素
现在流行的大多数语言都内置了迭代器,js中就有 for in | for of | forEach
等迭代器语法
使用迭代器,我们可以更方便的实现拓展。如果我们需要实现一个功能,它适用于一些不同的情况,每一种情况都有自己的逻辑需要处理,它们都有相似的调用接口,且相对独立。
具体的,书中给出了一个例子:
-
我们需要实现的功能是上传
-
上传功能的实现有以下几种方式
- 浏览器上传控件
- Flash
- 浏览器原生表单
它们之间是相互替换的关系,我们需要确认哪种方式在当前的浏览器中是可用的。
我们可以把每种获取 upload 对象的方法都封装在各自的函数里,然后使用一个迭代器,迭代获取这些 upload 对象,直到获取到一个可用的为止
var getActiveUploadObj = function(){
try{
return new ActiveXObject("TXFTNActiveX.FTNUpload"); // IE上传控件
} cache(e)
{
return false;
}
};
var getFlashUploadObj = function (){
if( supportFlash () ){
var str = "<object type = 'application/x-shockwave-flash'> </object>;"
return false;
}
}
}
var getFormUploadObj = function(){
var str = '<input name = "file" type = "file" class = "ui-file" />' // 表单上传
return $(str).appendTo($("body"));
};
它们三个函数都有同一个约定:如果该函数里面的 upload 对象是可用的,就让该函数返回对象,反之返回false,提示迭代器继续往后面迭代。
迭代器需要完成一下几步工作:
- 提供一个可迭代的方法,使得传入的方法依照优先级被循环迭代。
- 如果被迭代的函数返回一个对象,则表示找到了正确的 upload对象,反之如果该函数返回 false , 则让迭代器继续工作。
var iteratorUploadObj = function (){
var uploadObj = fn();
if( uploadObj !== false ){
return uploadObj;
}
}
var uploadObj = iteratorUploadObj( getActiveUploadObj , getFlashUploadObj , getFormUploadObj);
这样使用迭代器之后,我们可以看到,获取不同上传对象的方法被隔离在各自的函数里互不干扰,我们可以很方便的维护和拓展代码。比如,后来我们又给上传项目增加 Webkit 控件上传和 HTML 5 上传, 我们不需要修改原来的代码,只需要做下面的一些工作。
- 增加分别获取 Webkit 空间上传对象的函数
var getWebkitUploadObj = function (){
//...
}
var getHtml5UploadObj = function (){
//...
}
- 按照优先级把它们添加进迭代器
var uploadObj = iteratorUploadObj( getActiveUploadObj , getWebkitUploadObj, getFlashUploadObj, getHtml5UploadObj, getFormUploadObj);
小结:
- 迭代器模式是一种相对比较简单的设计模式, 很多语言都内置了它的实现
- 我们可以通过约定函数的接口,通过迭代器模式来提高代码的可拓展性。