問題背景

你有一個資料集合(陣列、鏈結串列、樹、圖),使用者想要逐一遍歷裡面的元素。如果把遍歷的邏輯暴露給外部(「你要自己知道陣列要用 index,鏈結串列要用 next 指針,樹要用遞迴」),使用者的程式碼就跟集合的內部結構緊密耦合——換一種集合結構就要改所有遍歷的程式碼。

Iterator Pattern 把「怎麼遍歷」封裝成一個獨立的 Iterator 物件,讓使用者只需要問「有沒有下一個」和「給我下一個」,不需要知道背後是什麼資料結構。


結構

Collection(Iterable)
  └── createIterator() → Iterator

Iterator
  ├── hasNext(): boolean
  └── next(): Element

Java 實作

// Iterator 介面(Java 標準庫已有)
// java.util.Iterator<T>
 
// 自定義範圍集合
class Range implements Iterable<Integer> {
    private final int start, end;
 
    Range(int start, int end) {
        this.start = start;
        this.end = end;
    }
 
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<>() {
            private int current = start;
 
            @Override
            public boolean hasNext() {
                return current < end;
            }
 
            @Override
            public Integer next() {
                return current++;
            }
        };
    }
}
 
// 使用:for-each 語法糖就是 Iterator 的包裝
for (int n : new Range(1, 5)) {
    System.out.println(n);  // 1 2 3 4
}

JavaScript / TypeScript

// JavaScript 用 Symbol.iterator 實作 iterable protocol
class InfiniteSequence {
    constructor(private start: number) {}
 
    [Symbol.iterator]() {
        let current = this.start;
        return {
            next: () => ({
                value: current++,
                done: false
            })
        };
    }
}
 
// for...of 透過 Symbol.iterator 工作
for (const n of new InfiniteSequence(1)) {
    if (n > 5) break;
    console.log(n);  // 1 2 3 4 5
}
 
// Generator function 是 Iterator 的語法糖
function* range(start: number, end: number) {
    for (let i = start; i < end; i++) yield i;
}

Python

class Range:
    def __init__(self, start, end):
        self.start = start
        self.end = end
 
    def __iter__(self):
        return RangeIterator(self.start, self.end)
 
class RangeIterator:
    def __init__(self, start, end):
        self.current = start
        self.end = end
 
    def __next__(self):
        if self.current >= self.end:
            raise StopIteration
        val = self.current
        self.current += 1
        return val
 
# Python 內建 range() 就是這個 pattern 的實作
for n in Range(1, 5):
    print(n)  # 1 2 3 4

實際應用

  • 資料庫結果集:Cursor-based pagination——每次 next() 拉下一頁,不需要一次載入全部
  • 檔案讀取:逐行讀取大檔案,不把整個檔案載入記憶體
  • Graph / Tree 遍歷:把 BFS 或 DFS 的遍歷邏輯封裝成 Iterator,使用者寫 for node in graph.bfs():
  • Lazy evaluation:Generator 讓 Iterator 支援無限序列,只在需要時計算下一個值