迭代器模式-遍历聚合对象中的元素

在开发中,我们经常使用到Iterator这个接口,我们很疑惑于这个接口的作用,认为集合已经实现了数据访问的方法,增加Iterator的意义在哪。本文我们将学习迭代器模式,用以探讨Iterator的作用。

1.1 迭代器模式概述

提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。

聚合对象拥有两个职责:1、存储数据;2、遍历数据。从依赖性来看,前者是聚合对象的基本职责,后者既是可以变化的,又是可分离的。将遍历数据的行为从聚合对象中分离出来,封装在一个被称为迭代器的对象中。由迭代器来提供遍历聚合对象内部数据的行为。

迭代器模式-遍历聚合对象中的元素_第1张图片

图 迭代器模式结构图

Iterator:抽象迭代器,定义了访问和遍历数据元素的接口。

ConcreteIterator:具体迭代器,实现了抽象迭代器接口,完成对聚合对象的遍历。同时通过游标来记录在聚合对象中所处的当前位置。

Aggregate:抽象聚合类,用于存储和管理元素对象。声明一个creteIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。

ConcreteAggregate:具体聚合类。实现createIterator()方法,返回一个与该具体聚合类对应的具体迭代器实例。

public interface Iterator {

    T first();
    T next();
    boolean hasNext();
    T currentItem();

}

public class ConcreteIterator implements Iterator{

    private final List list;
    private int cursor = 0;

    public ConcreteIterator(ConcreteAggregate list) {
        this.list = list.getList();
    }

    @Override
    public T first() {
        return list.get(0);
    }

    @Override
    public T next() {
        T t = list.get(cursor);
        cursor++;
        return t;
    }

    @Override
    public boolean hasNext() {
        return cursor < list.size();
    }

    @Override
    public T currentItem() {
        return list.get(cursor);
    }

}

public abstract class Aggregate {

    protected final List list = new ArrayList<>();

    public abstract Iterator createIterator();

    public List getList() {
        return list;
    }

    public void addItem(T item) {
        list.add(item);
    }

}

public class ConcreteAggregate extends Aggregate{

    @Override
    public Iterator createIterator() {
        return new ConcreteIterator<>(this);
    }

}

public class Client {

    public static void main(String[] args) {
        Aggregate aggregate = new ConcreteAggregate<>();
        aggregate.addItem("你好");
        aggregate.addItem("JAVA");
        aggregate.addItem("Hello");
        aggregate.addItem("world");
        aggregate.addItem("是谁说的");
        Iterator iterator = aggregate.createIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
//        运行结果:
//        你好
//        JAVA
//        Hello
//        world
//        是谁说的
    }

}

1.1.1 使用内部类实现迭代器

具体迭代器类和具体聚合类之间存在双重关系,我们可以使用内部类(JDK中的迭代器类就是通过这种方法来实现的)来实现迭代器,这样可以对外界隐藏具体迭代器的细节。

public class InnerAggregate extends Aggregate {

    @Override
    public Iterator createIterator() {
        return new InnerIterator();
    }

    private class InnerIterator implements Iterator{

        private int cursor = 0;

        @Override
        public T first() {
            return list.get(0);
        }

        @Override
        public T next() {
            T t = list.get(cursor);
            cursor++;
            return t;
        }

        @Override
        public boolean hasNext() {
            return cursor < list.size();
        }

        @Override
        public T currentItem() {
            return list.get(cursor);
        }

    }

}

public class Client {

    public static void main(String[] args) {
        Aggregate aggregate = new InnerAggregate<>();
        aggregate.addItem("躺平");
        aggregate.addItem("努力");
        Iterator iterator = aggregate.createIterator();
        while (iterator.hasNext())
            System.out.println(iterator.next());
//        运行结果:
//        躺平
//        努力
    }

}

2 JDK Collection的迭代器

Java提供了内置迭代器,像常用的List聚合接口,其继承了Collection接口。

迭代器模式-遍历聚合对象中的元素_第2张图片

图 ArrayList继承类图

迭代器模式-遍历聚合对象中的元素_第3张图片

图 Iterable与Collection 接口声明方法

ArrayList类使用了内部类Itr来实现内部迭代器。

迭代器模式-遍历聚合对象中的元素_第4张图片

图 ArrayList 的内部迭代器

迭代器模式-遍历聚合对象中的元素_第5张图片

图 ArrayList内部迭代器的继承类图

2.1 迭代器与Foreach

Java SE5引入了Iterable接口,该接口被foreach用来在序列中移动。(Collection继承了Iterable接口)

原理:foreach语句最终被编程器转换成对iterator.next()和iterator.hasNext()方法的调用。JDK屏蔽了这些实现细节。

迭代器模式-遍历聚合对象中的元素_第6张图片

图 foreach Java源代码与编译后的class对比图

3 优缺点

优点:

  1. 支持以不同的方式遍历一个聚合对象,只需用一个不同的迭代器替换原有迭代器即可改变遍历算法。
  2. 简化了聚合类,聚合对象中不需要再自行提供数据遍历方法。将聚合对象的访问与内部数据的存储分离,使得访问聚合对象无须了解其内部实现细节。

缺点:

1)增加了类的个数,设计难度较大,需充分考虑到系统将来的扩展。

4 适用场景

  1. 需要为一个聚合对象提供多种遍历方式。
  2. 访问一个聚合对象的内容而无须暴露它的内部表示。

你可能感兴趣的:(设计模式的艺术,java,算法,开发语言,设计模式,迭代器模式)