关键在于理解,迭代器模式就是以循环的方式访问聚合对象内的元素,而不必关心对象的内部构造(比如,数组需要维护索引,一般对象需要维护属性)。
迭代器模式可以将迭代的过程从业务逻辑中抽离出来,让 coder 更关注业务逻辑的编写。迭代器模式分为内部迭代器和外部迭代器。
内部迭代器只需调用一次,调用简单,适用场景也相对较小(数组、类数组、一般对象)。比如,lodash
库提供的遍历方法。ES6 给数组添加map
等方法,也是为了降低维护索引的复杂性,让开发者更关注具体元素。
外部迭代器需要通过外部调用控制迭代的过程,调用过程比较复杂,但是适用面更广。Iterator 迭代器(next
方法控制流程)、express
框架(处理请求用到的next
方法)。
可以减少对索引下标的依赖,还能减少大量if...else
语句,提高代码的可维护性、复用性。
迭代器模式在业务逻辑中的使用和策略模式在封装结构上是比较相似的,但使用的场景不同,一个用于策略的选择切换是随机顺序的,而另一个是抽离迭代过程,是一种顺序或倒叙的方向从始至终一致的切换(并且可以中止迭代)。
迭代器模式示例代码 -- 文件上传对象的选择切换:
// 文件上传,获取 文件上传模块 - if..else...tray...catch
var getUploadObj = function () {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload");
} catch (e) {
if (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'));
}
}
}
var getActiveUploadObj = function () {
try {
return new ActiveXObject("TXFTNActiveX.FTNUpload");
} 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"/>';
return $(str).appendTo($('body'));
}
var iteratorUploadObj = function() {
for (let i = 0, fn; fn=arguments[i++]) {
var uploadObj = fn();
if (uploadObj !== false) [
return uploadObj;
]
}
}
var uploadObj = iteratorUploadObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj);
参考资料:
- 《Javascript设计模式与开发实践》,曾探
- Javascript 设计模式 - 迭代器模式,前端君,juejin.cn/post/690405…