定义

所谓迭代器模式就是提供一种方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的表示。在实际的开发过程中,我们可能需要针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但是我们不希望在聚合对象的抽象接口层中充斥着各种不同的便利操作。这个时候我们就需要这样一种东西,它应该具备如下三个功能:

  • 能够遍历一个聚合对象。
  • 不需要了解聚合对象的内部结构。
  • 能够提供多种不同的遍历方式。

这三个功能就是迭代器模式需要解决的问题。作为一个功能强大的模式,迭代器模式把在元素之间游走的责任交给迭代器,而不是聚合对象。这样做就简化了聚合的接口和实现,也可以让聚合更专注在它所应该专注的事情上,这样做就更加符合单一责任原则。

迭代器模式是与集合共生共死的,一般来说,我们只要实现一个集合,就需要同时提供这个集合的迭代器,就像 java 中的 Collection,List、Set、Map 等,这些集合都有自己的迭代器。假如我们要实现一个这样的新的容器,当然也需要引入迭代器模式,给我们的容器实现一个迭代器。

角色

  • Iterator: 抽象迭代器:所有迭代器都需要实现的接口,提供游走聚合对象元素之间的方法。

  • ConcreteIterator: 具体迭代器。利用这个具体的迭代器能够对具体的聚合对象进行遍历。每一个聚合对象都应该对应一个具体的迭代器。

  • Aggregate: 抽象聚合类。

  • ConcreteAggregate: 具体聚合类。实现 creatorIterator() 方法,返回该聚合对象的迭代器。

优缺点

优点:

  • 简化了遍历方式

  • 可以提供多种遍历方式,比如说对有序列表,我们可以根据需要提供正序遍历,倒序遍历两种迭代器,用户用起来只需要得到我们实现好的迭代器,就可以方便的对集合进行遍历了。

  • 封装性良好,用户只需要得到迭代器就可以遍历,而对于遍历算法则不用去关心。

缺点:

  • 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐,像ArrayList,我们宁可愿意使用 for循环和 get方法来遍历集合。

实例

申明迭代器接口:

public interface Iterator {
    boolean hasNext();
    Object next();
}

实现迭代器具体类:

/**
 * 电影
 */
public class FilmIterator implements Iterator {

    private String[] filmItems;
    private int position = 0;

    public FilmIterator(String[] filmItems){
        this.filmItems = filmItems;
    }

    @Override
    public boolean hasNext() {
        if(position > filmItems.length-1 || filmItems[position] == null){
            return false;
        }
        return true;
    }

    @Override
    public Object next() {
        String film = filmItems[position];
        position ++;
        return film;
    }

}

/**
 * 电视频道
 */
public class TVChanneIterator implements Iterator {

    private List<String> tvChanneList;
    private int position = 0;

    public TVChanneIterator(List<String> tvChanneList) {
        this.tvChanneList = tvChanneList;
    }

    @Override
    public boolean hasNext() {
        if (position > tvChanneList.size() - 1 || tvChanneList.get(position) == null) {
            return false;
        }
        return true;
    }

    @Override
    public Object next() {
        String film = tvChanneList.get(position);
        position++;
        return film;
    }
}

申明节目接口:

public interface Program {

    void addItem(String title);

    Iterator createIrerator();
}

实现节目具体类:

public class FilmProgram implements Program {
    /**
     * 菜单最大长度
     */
    static final int MAX_ITEMS = 5;
    String[] filmItems;
    int index = 0;

    public FilmProgram() {
        filmItems = new String[MAX_ITEMS];
        addItem("大圣归来");
        addItem("大圣又归来");
        addItem("大圣还归来");
        addItem("大圣来都来了");
        addItem("大圣什么时候走");
    }

    @Override
    public void addItem(String title) {
        if (index > MAX_ITEMS) {
            System.out.println("容量已满....");
            return;
        }
        filmItems[index] = title;
        index++;
    }

    @Override
    public Iterator createIrerator() {
        return new FilmIterator(filmItems);
    }
}

public class TVChanneProgram implements Program{

    private List<String> tvChanneList;

    public TVChanneProgram(){
        tvChanneList = new ArrayList<>();
        addItem("欢乐戏剧人");
        addItem("吐槽大会");
        addItem("奇葩说");
    }
    @Override
    public void addItem(String title) {
        tvChanneList.add(title);
    }

    @Override
    public Iterator createIrerator() {
        return new TVChanneIterator(tvChanneList);
    }
}

调用:

public static void main(String[] args) {
    TVChanneProgram tvChanneProgram = new TVChanneProgram();
    Iterator irerator1 = tvChanneProgram.createIrerator();
    System.out.println("======显示电视频道======");
    while(irerator1.hasNext()){
        System.out.println(irerator1.next());
    }
    System.out.println("======显示电影======");
    FilmProgram filmProgram = new FilmProgram();
    Iterator irerator2 = filmProgram.createIrerator();
    while(irerator2.hasNext()){
        System.out.println(irerator2.next());
    }
}

控制台输出:

======显示电视频道======
欢乐戏剧人
吐槽大会
奇葩说
======显示电影======
大圣归来
大圣又归来
大圣还归来
大圣来都来了
大圣什么时候走
01-20 06:32