一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
概念:
提供一种方法 , 顺序访问集合对象中的各个元素, 而不暴露该对象的内部表示。
优点:
- 分离了集合对象的遍历行为
- 抽象出了迭代器负责集合对象的遍历,可以让外部的代码透明的访问集合内部的数据
缺点:
类的个数成对增加;迭代器模式,将存储数据,遍历数据两个职责拆分;如果新添加一个集合类,需要增加该 集合类对应的迭代器类,类的个数成对增加,在一定程度上,增加了系统复杂性。
使用场景:
- 内容保密 : 访问集合对象的内容,无需暴露内部表示
- 统一接口 : 为遍历不同的集合结构,提供统一接口
示例代码:
题目:书(Book)放置到书架(BookSelf)中,并将书的名字按顺序显示出来
代码实现:
class Book {
constructor(name) {
this.name = name;
}
}
class BookSelf {
constructor(maxSize) {
this.books = new Array(maxSize);
this.last = 0;
this.maxSize = maxSize;
}
appendBook(book) {
if (this.last < this.maxSize) {
this.books[this.last] = book;
this.last++;
}
}
getLength() {
return this.last;
}
getBookAt(index) {
return this.books[index];
}
iterator() {
return new MyIterator(this);
}
}
class MyIterator {
constructor(bookSelf) {
this.index = 0;
this.bookSelf = bookSelf;
}
next() {
const book = this.bookSelf.getBookAt(this.index);
this.index++;
return book;
}
hasNext() {
if (this.index < this.bookSelf.getLength()) {
return true;
} else {
return false;
}
}
}
// 开始调用
const bookShelf = new BookSelf(4);
bookShelf.appendBook(new Book('a'));
bookShelf.appendBook(new Book('b'));
bookShelf.appendBook(new Book('c'));
bookShelf.appendBook(new Book('d'));
bookShelf.appendBook(new Book('e'));
bookShelf.appendBook(new Book('f'));
bookShelf.appendBook(new Book('g'));
bookShelf.appendBook(new Book('h'));
bookShelf.appendBook(new Book('i'));
const myIterator = bookShelf.iterator();
while (myIterator.hasNext()) {
let book = myIterator.next();
console.log(book, 'book');
//Book { name: 'a' } book
//Book { name: 'b' } book
//Book { name: 'c' } book
//Book { name: 'd' } book
}
类比: 由此可以类比ES6中的迭代器,见代码:
var arr = [1, 2, 3];
var nodeList = document.getElementsByClassName('test');
var map = new Map();
map.set('one', 1);
map.set('two', 2);
var set = new Set([1, 2, 3, 4]);
const each = (data) => {
let $data = data[Symbol.iterator]();
let item = {
done: false,
};
while (!item.done) {
item = $data.next();
if (!item.done) {
console.log(item, 'item');
}
}
};
each(arr);
//{ value: 1, done: false } item
//{ value: 2, done: false } item
//{ value: 3, done: false } item
each(nodeList);
each(map);
//{ value: [ 'one', 1 ], done: false } item
//{ value: [ 'two', 2 ], done: false } item
each(set);
//{ value: 1, done: false } item
//{ value: 2, done: false } item
//{ value: 3, done: false } item
//{ value: 4, done: false } item
类比结果:与ES6中的迭代器基本一样,最重要的就是next指针以及done属性(用来结束循环)。
总结:
自定义适配器模式灵活性更高,可以自定义遍历数据集合的顺序。