迭代器模式提供一種方法,能夠順序存取一個容器物件中的各個元素,而無需暴露該物件的內部結構。屬於行為型設計模式。
若問 Java 中應用最廣泛的設計模式,答案非單例、非工廠、非策略,而是迭代器模式。來看一段經典代碼:
public static void print(Collection coll) {
Iterator it = coll.iterator();
while (it.hasNext()) {
String str = (String) it.next();
System.out.println(str);
}
}
此方法用於迭代打印字符串集合,內部便使用了迭代器模式。Java 語言已完整實作迭代器模式,Iterator 即迭代器之意。
迭代器與聚集(集合、容器)息息相關。聚集可視為一個裝載物件的容器,如 List、Set、Map,甚至陣列。迭代器的作用是將容器中的物件逐一遍歷出來。
iterator() 方法,如 Collection、List、Set。ArrayList、LinkedList、HashSet。first()、next()、isDone()(或 hasNext())、remove()。迭代器模式的規範較寬鬆,具體實作多樣。在 Java Collections 中,具體迭代器通常以內部類形式定義於容器類中,這樣既保護了容器的封裝性,又提供了遍歷算法的擴展點。
以下為 AbstractList 中迭代器實作的核心片段:
public abstract class AbstractList extends AbstractCollection implements List {
// ...
public Iterator iterator() {
return new Itr();
}
private class Itr implements Iterator {
int cursor = 0;
int lastRet = -1;
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public Object next() {
checkForComodification();
try {
Object next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet == -1) throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor) cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
}
get() 更直接。迭代器模式與聚集共生共存。一般情況下,實作一個新容器時需同時提供其迭代器。但現代語言的標準庫已內建完善的容器與迭代器,開發者極少需自行實作,直接使用現有 API 即可。