迭代器模式

面向对象编程里,迭代器模式是一种设计模式,是一种最简单也最常见的设计模式。它可以让用户透过特定的接口巡访容器中的每一个元素而不用了解底层的实现。

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

接口

《设计模式》建议合理的接口该要有:

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

问题

  • 在巡访过程中,容器可能会被外部改变。譬如新增或删除一个元素。

另见