美文网首页设计模式系列篇
设计模式系列篇(十六)——迭代器模式

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

作者: 复旦猿 | 来源:发表于2020-09-02 23:14 被阅读0次

    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

    写在最后

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

    相关文章

      网友评论

        本文标题:设计模式系列篇(十六)——迭代器模式

        本文链接:https://www.haomeiwen.com/subject/gyegsktx.html