首页 > 代码库 > 设计模式之迭代器模式

设计模式之迭代器模式

GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。

它的目的:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。[GOF 《设计模式》]

如果大家只看定义的话估计也不太清楚吧,怎么说呢,从简单来讲,大家可以把它理解为是一个抽象化的for循环语句。

for语句:

for(int i=0;i<arr.length;i++){
  System.out.printIn(arr[i]);
}

 

模式结构图

    Iterator模式结构图如下:

 

有下面四个角色:
  1) 迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的接口。

  2) 具体迭代器角色(Concrete Iterator):具体迭代器角色要实现迭代器接口,并要记录遍历中的当前位置。

  3) 容器角色(Container):容器角色负责提供创建具体迭代器角色的接口。

  4) 具体容器角色(Concrete Container):具体容器角色实现创建具体迭代器角色的接口——这个具体迭代器角色于该容器的结构相关。

 

下面我们通过一个简单的例子来实现:

首先看一下类图:

 

下面我贴上代码:

public  interface Aggregate {
    public abstract Iterator iterator();
}
public interface Interator {
    public abstract boolean hasNext();
    public abstract Object next();
}
public class Book {
    private String name = "";

    public Book(String name) {
        this.name=name;
    }
    public String getName(){
        return name;
    }
}
public class BookShelf implements Aggregate {
    private Book[] books;
    private int last = 0;

    public BookShelf(int maxsize) {
        this.books = new Book[maxsize];
    }

    public Book getBookAt(int index) {
        return books[index];
    }

    public void appendBook(Book book) {
        this.books[last] = book;
        last++;
    }

    public int getLength() {
        return last;
    }

    @Override
    public Iterator iterator() {

        return new BookShelfIterator(this);

    }

}
public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf;
    private int index;

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {
        if (index < bookShelf.getLength()) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);// 得到当前位置的book
        index++;// 进到下一个位置的book
        return book;
    }

    @Override
    public void remove() {
        // TODO Auto-generated method stub

    }

}
public class Main {

    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(4);
        bookShelf.appendBook(new Book("A"));
        bookShelf.appendBook(new Book("B"));
        bookShelf.appendBook(new Book("C"));
        bookShelf.appendBook(new Book("D"));
        Iterator it = bookShelf.iterator();
        while (it.hasNext()) {
            Book book = (Book) it.next();
            System.out.println("" + book.getName());
        }

    }

}

测试结果:

 

 

一个简单的容器为什么还要定义成一个接口呢?

如果对如何使用抽象类和接口还不太清楚的话,估计会很纠结于这个问题。因为只用具体类就能解决所有问题的感觉会让人不知不觉的上瘾。

其实原因很简单,过度依赖具体类会提高类与类的耦合度,增加零部件复用的困难。为了降低耦合度,让类作为零部件再利用,必须引进抽象类和接口的概念。也就是实现软件的“高内聚低耦合”,这是以前软件工程老师常提到的话了。

 

迭代器模式的优点:

  1. 它支持以不同的方式遍历一个聚合对象 : 复杂的聚合可用多种方式进行遍历。迭代器模式使得改变遍历算法变得很容易 : 仅需用一个不同的迭代器的实例代替原先的实例即可。你也可以自己定义迭代器的子类以支持新的遍历。
  2. 迭代器简化了聚合的接口 有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了。这样就简化了聚合的接口。
  3. 在同一个聚合上可以有多个遍历 每个迭代器保持它自己的遍历状态。因此你可以同时进行多个遍历。
  4. 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足“开闭原则”的要求。

迭代器模式的缺点:

  由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

 

迭代器模式的适用范围:

    1. 访问一个容器对象的内容而无需暴露它的内部表示。
    2. 支持对容器对象的多种遍历。
    3. 为遍历不同的容器结构提供一个统一的接口(多态迭代)。

 

总结:

Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据。