迭代器模式

物件導向程式設計裡,迭代器模式是一種設計模式,是一種最簡單也最常見的設計模式。它可以讓使用者透過特定的介面巡訪容器中的每一個元素而不用了解底層的實作。

此外,也可以實作特定目的版本的迭代器。

介面

《設計模式》建議合理的介面該要有:

public interface Iterator
{
    public Object First();
    public Object Next();
    public boolean isDone();
    public Object CurrentItem();
}

範例

interface Iterator{
    Object First();
    Object Next();
    boolean IsDone();
    Object CurrentItem();
}

abstract class Aggregate{
    abstract Iterator CreateIterator();
}

class ConcreteIterator implements Iterator{
    private List<Object> list = new ArrayList<Object>();
    private int curr=0;
    public ConcreteIterator(List<Object> list){
        this.list = list;
    }

    public Object First(){
        return list.get(0);
    }

    public Object Next(){
        Object ret = null;
        curr++;
        if(curr < list.size()){
            ret = list.get(curr);
        }
        return ret;
    }

    public boolean IsDone(){
        return curr>=list.size()?true:false;
    }

    public Object CurrentItem(){
        return list.get(curr);
    }
}

class ConcreteAggregate extends Aggregate{
    private List<Object> list = new ArrayList<Object>();
    public ConcreteAggregate(List<Object> list){
        this.list = list;
    }
    public Iterator CreateIterator(){
        return new ConcreteIterator(list);
    }
}

class client{
    public static void main(String[] args){
    List<Object> list = new ArrayList<Object>();
    list.add("miner");
    list.add("any");
    Aggregate agg = new ConcreteAggregate(list);
    Iterator iterator = agg.CreateIterator();
    iterator.First();
    while(!iterator.IsDone()){
        System.out.println(iterator.CurrentItem());
        iterator.Next();
        }
    }
}

在 Python 中,迭代器是遵循迭代協定的物件。使用者可以使用 iter() 以從任何序列得到迭代器(如 list, tuple, dictionary, set 等)。另一個方法則是建立一個另一種形式的迭代器 —— generator 。要取得下一個元素,則使用成員函式 next()(Python 2)或函式 next() function (Python 3) 。當沒有元素時,則引發 StopIteration 此例外。若要實作自己的迭代器,則只要實作 next()(Python 2)或 __next__()( Python 3)。

以下為兩個例子:

# 從序列得到
x = [42, "test", -12.34]
it = iter(x)
try:
  while True:
    x = next(it) # 在 Python 2 中,要改成 it.next()
    print x
except StopIteration:
  pass

# generator
def foo(n):
  for i in range(n):
    yield i

it = foo(5)
try:
  while True:
    x = next(it) # 在 Python 2 中,要改成 it.next()
    print x
except StopIteration:
  pass

For Each…Next(Visual Basic)或者foreach(C#)迴圈語句,將呼叫迭代器遍歷一個序列,每次取得一個返回值。

迭代器可以作為一個方法或屬性的get訪問器,其中的Yield (Visual Basic)或yield return (C#)語句返回迭代器的返回值,並記住當前執行的位置。下次再呼叫迭代器,從該執行位置恢復執行,直至迭代器代碼執行完或者遇到Exit Function或Return語句(Visual Basic)或yield break語句(C#) 。編譯器把迭代器作為一個狀態機的類。

Sub Main()
    Dim days As New DaysOfTheWeek()
    For Each day As String In days
        Console.Write(day & " ")
    Next 
    ' Output: Sun Mon Tue Wed Thu Fri Sat
    Console.ReadKey()
End Sub 

Private Class DaysOfTheWeek
    Implements IEnumerable

    Public days =
        New String() {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}

    Public Iterator Function GetEnumerator() As IEnumerator _
        Implements IEnumerable.GetEnumerator

        ' Yield each day of the week. 
        For i As Integer = 0 To days.Length - 1
            Yield days(i)
        Next 
    End Function 
End Class

問題

  • 在巡訪過程中,容器可能會被外部改變。譬如新增或刪除一個元素。

另見