设计模式系列篇(十六)——迭代器模式

What

迭代器模式(Iterator Design Pattern),提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。该模式用来遍历集合对象。这里说的“集合对象”也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,比如数组、链表、树、图、跳表。迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一。

Why

迭代器模式有以下几个优点:

  1. 它支持以不同的方式遍历一个聚合对象。
  2. 迭代器简化了聚合类。
  3. 在同一个聚合上可以有多个遍历。
  4. 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

When

开篇的时候我们就讲了,迭代器模式适用于遍历一个聚合对象时使用。

How

一个完整的迭代器模式,一般会涉及容器和容器迭代器两部分内容。为了达到基于接口而非实现编程的目的,容器又包含容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。容器中需要定义 iterator() 方法,用来创建迭代器。迭代器接口中需要定义 hasNext()、currentItem()、next() 三个最基本的方法。容器对象通过依赖注入传递到迭代器类中。
我们知道,线性数据结构包括数组和链表,在大部分编程语言中都有对应的类来封装这两种数据结构,在开发中直接拿来用就可以了。假设在这种新的编程语言中,这两个数据结构分别对应 ArrayList 和 LinkedList 两个类。除此之外,我们从两个类中抽象出公共的接口,定义为 List 接口,以方便开发者基于接口而非实现编程,编写的代码能在两种数据存储结构之间灵活切换。现在,我们针对 ArrayList 和 LinkedList 两个线性容器,设计实现对应的迭代器。我们定义一个迭代器接口 Iterator,以及针对两种容器的具体的迭代器实现类 ArrayIterator 和 ListIterator。
具体代码如下:

public interface List<E> {
    Iterator<E> iterator();

    void add(E element);

    void remove(int index);

    E get(int index);

    int length();
}

public class ArrayList<E> implements List<E> {
    private Object[] array;
    private static final Integer DEFAULT_LENGTH = 10;
    private int len;

    public ArrayList() {
        array = new Object[DEFAULT_LENGTH];
        len = 0;
    }

    @Override
    public Iterator<E> iterator() {
        return new ArrayIterator<>(this);
    }

    @Override
    public void add(E element) {
        array[len++] = element;
    }

    @Override
    public void remove(int index) {
        int numMoved = len - index - 1;
        if (numMoved > 0)
            System.arraycopy(array, index + 1, array, index,
                    numMoved);
        array[--len] = null;
    }

    @Override
    public E get(int index) {
        return (E) array[index];
    }

    @Override
    public int length() {
        return this.len;
    }
}
public interface Iterator<E> {
    boolean hasNext();
    void next();
    E currentItem();
}

public class ArrayIterator<E> implements Iterator<E> {
    private int cursor;
    private ArrayList<E> arrayList;

    public ArrayIterator(ArrayList<E> arrayList) {
        this.arrayList = arrayList;
    }

    @Override
    public boolean hasNext() {
        return cursor < arrayList.length();
    }

    @Override
    public void next() {
        cursor++;
    }

    @Override
    public E currentItem() {
        return arrayList.get(cursor);
    }
}

限于篇幅,这里给出的ArrayList的实现非常简单,甚至有些边界条件都没有处理,有兴趣的话,大家可以去看下java.util.ArrayList的实现。

测试类如下:

public class TestMain {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        Iterator iterator = list.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.currentItem());
            iterator.next();
        }

        list.remove(0);
        iterator = list.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.currentItem());
            iterator.next();
        }
    }
}

输出如下:

1
2
3
2
3

代码地址

i-learning

写在最后

如果你觉得我写的文章帮到了你,欢迎点赞、评论、分享、赞赏哦,你们的鼓励是我不断创作的动力~

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容