Design Pattern: Iterator 模式
 

2009-09-18 来源:riabook.cn

 

在Java中提供有ArrayList类,您可以用它来设计一个动态的物件阵列,并在适当的时候取出阵列中的物件,假设今天您要循序的访问ArrayList中的所有物件,则您可能采取这样的方式:

  • Main.java
    import java.util.*;
    
    public class Main {
        public static void main(String[] args) {
            List arrayList = new ArrayList();
    
            for(int i = 0; i < 10; i++) 
                arrayList.add("Test " + i);
    
            for(int i = 0; i < 10; i++) 
                System.out.println(arrayList.get(i).toString()); 
        } 
    } 
    

在这个例子中,很幸运的,您的ArrayList物件可以透过get()方法,使用索引加上回圈的方式来循序访问 ArrayList中的所有物件,不过并不是每一个聚合(aggregate)物件的内部实作都会是有索引结构的,也许是key/value的方式,或者是其它的方式。

由于每个聚合物件的内部实作方式不尽相同,如果您想要循序的访问聚合物件中所有的物件,您要为不同的聚合物件设计不同的循序访问介面,然而这并不是个好方法,结果是您设计的聚合物件上将会有很多的循序访问方法,而使用您的聚合物件的人,还必须知道这个聚合物件的类型,才能进一步知道如何使用它所提供的方法。

与其在聚合物件上直接设计遍访的介面,不如设计一个介面Iterator,上面设计有统一的循序访问,当您想要循序访问聚合物件中的物件时,将聚合物件中的物件加以包装为一个Iterator后返回,客户端只要面对Iterator所提供的介面,而不用面对为数众多的聚合物件。

采取迭代器(Iterator)的方法,一个迭代器提供一个特定的遍访方法,而使得设计人员无需关心聚合物件的类型(可能是ArrayList或 LinkedList等),例如上面这个程式可以改为:

  • Main.java
    import java.util.*;
    
    public class Main { 
        public static void main(String[] args) { 
            List arrayList = new ArrayList();
            for(int i = 0; i < 10; i++) 
                arrayList.add("Test " +i);
            visit(arrayList.iterator()); 
        }
    
        public static visit(Iterator iterator) {
            while(iterator.hasNext()) 
                System.out.println(iterator.next().toString()); 
        }
    }

如上所示的,iterator()方法会传回一个Iterator物件,这个物件提供的循序访问的统一介面,如果您查询 Java API中的LinkedList所提供的方法,您会发现它的iterator()方法同样也传回Iterator物件,您无需关心您所使用的是 ArrayList或LinkedList,使用Iterator可以让您以相同的方法来遍访聚合物件的内容,以上例来说,visit()方法就可以重用,它不特地服务于ArrayList或LinkedList。

Iterator

意这个模型是简化过后的版本,并不是Java中的设计,这么作只是为了方便说明,这个图形说明了Iterator模式的基本结构。再来看另一个在 Thinking in Java的例子,可以说明使用Iterator的好处:

  • HamsterMaze.java
import java.util.*; 

class Hamster { 
    private int hamsterNumber; 
    Hamster(int i) { hamsterNumber = i; } 
    public String toString() { 
        return "This is Hamster #" + hamsterNumber; 
    } 
} 

class Printer { 
    static void printAll(Iterator e) { 
        while(e.hasNext()) {
            System.out.println(e.next()); 
        }
    } 
} 

public class HamsterMaze { 
    public static void main(String[] args) { 
        ArrayList v = new ArrayList(); 
        for(int i = 0; i < 3; i++) {
            v.add(new Hamster(i)); 
        }
        Printer.printAll(v.iterator()); 
    } 
} 

对于Printer物件来说,它完全不用知道聚合物件的类型到底是ArrayList或是LinkedList,您只要传回Iterator物件就可以了,剩下的就是使用Iterator物件所提供的循序访问方法来访问所有的物件。

Iterator模式的 UML 结构图如下所示:

Iterator

使用Iterator模式,可以将循序访问聚合对象的方法从该对象中分离出来,从而使得聚合对象的设计单纯化,对客户来说,他所要知道的是所使用的 Iterator而不是聚合对象的类型。


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织