迭代器模式

一、概述

一般问题:数据集合固定,而遍历方式多变。

核心方案:提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

设计意图:从学习编程的循环语句以来,每次说到遍历,满脑子只会想到for和while,我们都有面向过程编程的基因。然而在面向对象编程里,一切皆为对象;在设计模式里,一切变化的都应当分离,一起能拆散的都是假耦合!客户端遍历集合,如果使用for或while就必须知道集合的内部数据结构,这就带来了耦合,而且是没有必要的。所以遍历要对象化,从而保证集合独立解耦。而且这种思维已经渗入到各大语言内部。比如,java提供了工具类Iterator,专门来做集合遍历。

迭代器模式类图:

  • Aggregation是集合接口,声明了getIterator()方法,返回一个Iterator对象;
  • Iterator是遍历器接口,声明hasNext()和next()两个遍历相关方法。

 二、应用实战

我们以Android中的ArrayList为例,来讲一下它用到的遍历模式,先看它的相关类图:

其中ArrayList间接实现Iterable<E>接口,Iterable<E>接口主要声明集合支持iterator()和forEach()两种遍历方式。

/**
 * Implementing this interface allows an object to be the target of
 * the "for-each loop" statement. See
 */
public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();

    /**
     * Performs the given action for each element of the {@code Iterable}
     * until all elements have been processed or the action throws an
     * exception.  Unless otherwise specified by the implementing class,
     * actions are performed in the order of iteration (if an iteration order
     * is specified).  Exceptions thrown by the action are relayed to the
     * caller.
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
}

Iterator遍历器接口,主要声明hasNext()和next()两个遍历方法:

/**
 * An iterator over a collection.  {@code Iterator} takes the place of
 * {@link Enumeration} in the Java Collections Framework.  Iterators
 * differ from enumerations in two ways:
 */
public interface Iterator<E> {
    /**
     * Returns {@code true} if the iteration has more elements.
     * (In other words, returns {@code true} if {@link #next} would
     * return an element rather than throwing an exception.)
     *
     * @return {@code true} if the iteration has more elements
     */
    boolean hasNext();

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration
     * @throws NoSuchElementException if the iteration has no more elements
     */
    E next();
}

ArrayList的遍历器Itr实现Iterator接口,实现了hasNext()和next()两个遍历方法:

    private class Itr implements Iterator<E> {
        // Android-changed: Add "limit" field to detect end of iteration.
        // The "limit" of this iterator. This is the size of the list at the time the
        // iterator was created. Adding & removing elements will invalidate the iteration
        // anyway (and cause next() to throw) so saving this value will guarantee that the
        // value of hasNext() remains stable and won't flap between true and false when elements
        // are added and removed from the list.
        protected int limit = ArrayList.this.size;

        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            return cursor < limit;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            int i = cursor;
            if (i >= limit)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
}

三、总结

总结:迭代器模式是一种行为型设计模式,这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示,实现了数据与遍历的解耦。

优点:

  • 它支持以不同的方式遍历一个聚合对象。
  • 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点:增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

 

posted @ 2019-06-27 10:06  西贝雪  阅读(214)  评论(0编辑  收藏  举报