定义
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。
迭代器模式是一个非常简单的设计模式。简单到迭到很多时候我们都不认为它是一种设计模式,因为目前的绝大部分语言都内置了迭代器,比如JavaScript中的Array.prototype.forEach
。
实现
迭代器模式的实现非常简单,如下所示
const each = (ary, callback) => {
for (let i = 0, l = ary.length; i < l; i++) {
callback.call(ary[i], i, ary[i]);
}
};
each([1, 2, 3], function (i, n) {
console([i, n]);
});
通过each
方法将ary
数组每个元素传入callback
中处理,这就是迭代器模式。
内部迭代器和外部迭代器
迭代器可以分为内部迭代器和外部迭代器,上述实现的each
函数属于内部迭代器,each
函数的内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用。
那么现在有一个需求,构造一个函数来比较ary1
和ary2
的内容是否相等。是否可以用each
函数实现。当然可以了,如下这样实现:
const compare = (ary1, ary2) => {
if (ary1.length !== ary2.length) {
throw new Error('ary1 和 ary2 不相等');
}
each(ary1, function (i, n) {
if (n !== ary2[i]) {
throw new Error('ary1 和 ary2 不相等');
}
});
console.log('ary1 和 ary2 相等');
};
compare( [ 1, 2, 3 ], [ 1, 2, 5 ] ); // 'ary1 和 ary2 不相等' ;
但是这样实现太不优雅了,each
函数中的迭代规则已经在内部定义好了,无法改变,这也是内部迭代器的缺点。
要让compare
函数内部实现得优雅点,得借助外部迭代器。外部迭代器必须显式地请求迭代下一个元素。
外部迭代器增加了一些调用的复杂度,但相对也增强了迭代器的灵活性,我们可以手工控制迭代的过程或者顺序。
下面用外部迭代器来实现compare
函数。
const Iterator = function (obj) {
let current = 0;
const next = function () {
current += 1;
};
const isDone = function () {
return current >= obj.length;
};
const getCurrItem = function () {
return obj[current];
};
return {
next: next,
isDone: isDone,
getCurrItem: getCurrItem
}
};
const compare = function (iterator1, iterator2) {
while (!iterator1.isDone() && !iterator2.isDone()) {
if (iterator1.getCurrItem() !== iterator2.getCurrItem()) {
throw new Error('iterator1 和 iterator2 不相等');
}
iterator1.next();
iterator2.next();
}
console.log('iterator1 和 iterator2 相等');
}
const iterator1 = Iterator([1, 2, 3]);
const iterator2 = Iterator([1, 2, 3]);
compare(iterator1, iterator2); // 输出:iterator1 和 iterator2 相等
其中 Iterator
函数就是一个外部迭代器,返回一个对象,其中暴露出一个getCurrItem
方法来显式地请求迭代下一个元素。
外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。
如何终止迭代
很简单,在需要终止的地方写上,return false
。