迭代器可以分为内部迭代器和外部迭代器。
内部迭代器内部定义好了迭代规则,外部只需要一次初始调用。
外部迭代器较为复杂,但是可以手工控制迭代过程以及顺序,更加灵活。
一个简单的外部迭代器的例子。
1 var Iterator = function(obj) { 2 var current = 0; 3 4 var next = function() { 5 current += 1; 6 } 7 8 var isDone = function() { 9 return current >= obj.length; 10 } 11 12 var getCurrentItem = function() { 13 return obj[current]; 14 } 15 16 return { 17 next, 18 isDone, 19 getCurrentItem, 20 length: obj.length 21 } 22 23 }
外部迭代器调用方式较为复杂,但适用面更广,能满足更多变的需求。
无论是内部迭代器还是外部迭代器,只要被迭代的聚合对象拥有length属性而且可以用下标访问,那它就可以被迭代。(length属性应该看具体规则而定)
迭代器还可以分为顺序,倒序和终止迭代器,可以灵活选择。
应用举例:
业务场景:根据不同浏览器获取相应的上传组件对象:
1 var getUploadObj = function() { 2 try{ 3 return new ActiveXObject('TXFTNActiveX.FINUpload'); // IE上传控件 4 }catch(e) { 5 if (supportFlash()) { 6 var str = '<Object type="application/x-shockwave-flash"></Object>'; 7 return $('str').appendTo($('body')); 8 }else { 9 var str = '<input name="file" type="file"/>'; // 表单上传 10 return $(str).appendTo($('body')); 11 } 12 } 13 }
这样组织代码的缺点是显而易见的,里面充斥了try,catch和if条件分支,第一是很难阅读,第二是严重违反开闭原则,如果之后要增加其他的上传方式,就得深入到代码的内部,
继续往函数里增加条件分支。
迭代器模式的实现思路:
1.将每个获取上传方式的方法封装在各自的函数里;
2.提供一个可以被迭代的方法,使得每种方法按照指定的优先级循环迭代;
3.当迭代器获取到指定的内容时,表示获取到指定的upLoad对象,停止迭代,其他情况让迭代器继续工作。
具体实现如下:
1 var getActiveUploadObj = function() { 2 try{ 3 return new ActiveXObject('TXFTNActiveX.FINUpload'); // IE上传控件 4 }catch(e) { 5 return false; 6 } 7 } 8 9 var getFlashUploadObj = function() { 10 if (supportFlash()) { 11 var str = '<Object type="application/x-shockwave-flash"></Object>'; 12 return $('str').appendTo($('body')); 13 } 14 return false; 15 } 16 17 var getFormUploadObj = function() { 18 var str = '<input name="file" type="file"/>'; // 表单上传 19 return $(str).appendTo($('body')); 20 } 21 22 var iteratorObj = function() { 23 for(var i = 0, fn; fn = arguments[i++]; ) { 24 var uploadObj = fn(); 25 if (uploadObj !== false) { 26 return uploadObj; 27 } 28 } 29 } 30 31 var uploadObj = iteratorObj(getActiveUploadObj, getFlashUploadObj, getFormUploadObj)
之后如果要增加其它上传组件,只要定义获取组件的方法并将它们按照优先级添加到迭代器里就可以了。