迭代器模式与命令模式详解(2)

然后,编写客户端代码:


public class Test {
    public static void main(String[] args) {
        Course java = new Course("Java架构");
        Course javaBase = new Course("Java基础");
        Course design = new Course("设计模式");
        Course ai = new Course("人工智能");

        ICourseAggregate aggregate = new CourseAggregateImpl();
        aggregate.add(java);
        aggregate.add(javaBase);
        aggregate.add(design);
        aggregate.add(ai);

        System.out.println("===========课程列表==========");
        printCourse(aggregate);

        aggregate.remove(ai);

        System.out.println("===========删除操作之后的课程列表==========");
        printCourse(aggregate);
    }

    private static void printCourse(ICourseAggregate aggregate) {
        Iterator<Course> i = aggregate.iterator();
        while (i.hasNext()){
            Course course = i.next();
            System.out.println("《" + course.getName()  + "》");
        }
    }
}


运行结果如下:


迭代器模式与命令模式详解(2)


看到这里,小伙伴们肯定会有一种似曾相识的感觉,让人不禁想起我们每天都在用的JDK

自带的结合迭代器。下面我们就来看看源码中是如何运用迭代器的。


三、迭代器模式在源码中的体现


先来看JDK中大家非常熟悉的Iterator源码 :


public interface Iterator<E> {
    boolean hasNext();

    E next();

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}


从上面代码中,我们看到两个主要的方法定义hasNext()和 next()方 法 ,和我们自己写的完 全一致。


另外,从上面的代码中,我们看到removeO方法实现似曾相识。其实是在组合模式中我们 见到过。迭代器模式和组合模式,两者似乎存在一定的相似性。组合模式解决的是统一树形结


构各层次访问接口,迭代器模式解决的是统一各集合对象元素遍历接口。虽然他们的适配场景


不同,但核心理念是相通的。


下面接看来看Iterator的实现类,其实在我们常用的ArrayList中有一个内部实现类Itr ,它

就实现了 Iterator接口 :


public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private class Itr implements Iterator<E> {
        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 != size;
        }

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

        ...
    }
}
private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor - 1;
    }

    ...
}


它增加了 hasPreviousQ方法是否还有上一个等这样的判断。另外还有SubList对子集合的迭代处理。

当然,迭代器模式在MyBatis中也是必不可少的,来看一个Defaultcursor类 :


public class DefaultCursor<T> implements Cursor<T> {
    ...
    private final CursorIterator cursorIterator = new CursorIterator();
}


首先它实现了 Cursor接 口 ,而且定义了一个成员变量cursoriterator , 我继续查看

Cursoriterator的源代码发现, 它 是 Defaultcursor的一个内部类,并且实现了 JDK中的

Iterater 接口。


四、迭代器模式的优缺点

优点:


1、 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的集合对

象 ;


2、 简化集合对象接口 :迭代器模式将集合对象本身应该提供的元素迭代接口抽取到了迭代器中 ,使集合对象无须关心具体迭代行为;


3、 元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使的同种元素聚合结构可以有不同的迭代行为;


4、解耦迭代与集合:迭代器模式 封装了具体的迭代算法,迭代算法的变化,不会影响到集合对象的架构。


缺点:


1、对于比较简单的遍历(像数组或者有序列表) ,使用迭代器方式遍历较为繁琐。

在日常开发当中,我们几乎不会自己写迭代器。除非我们需要定制一个自己实现的数据结构

对应的迭代器,否则,开源框架提供给我们的API完全够用。


上一篇:R 的用户自定义函数| 学习笔记


下一篇:4大工业物联网网络的实施战略