迭代器模式(Iterator)

214

迭代器模式(Iterator)

Iterator:迭代器模式是一种行为设计模式,提供一种方法顺序访问一个集合中的各个元素,而又不暴露对象的底层表现形式。

/**
 * 迭代器模式
 *
 * @author CAI
 * @time 2020/11/16
 */
public class IteratorPattern {

    public static void main(String[] args) {
        CourseCollection courses = initCollection();
        CourseIterator all = courses.iterator(MajorType.ALL);
        while (all.hasNext()) {
            Course course = all.next();
            System.out.println(course);
        }

        System.out.println();
        System.out.println("<----------------------------->");
        System.out.println();

        CourseIterator cs = courses.iterator(MajorType.COMPUTER_SCIENCES);
        while (cs.hasNext()) {
            Course course = cs.next();
            System.out.println(course);
        }
    }

    private static CourseCollection initCollection() {
        CourseCollection courses = new CourseCollectionImpl();
        courses.add(new Course("计算机网络", MajorType.COMPUTER_SCIENCES));
        courses.add(new Course("计算机操作系统", MajorType.COMPUTER_SCIENCES));
        courses.add(new Course("计算机组成原理", MajorType.COMPUTER_SCIENCES));
        courses.add(new Course("数据结构与算法", MajorType.COMPUTER_SCIENCES));
        courses.add(new Course("生物化学", MajorType.BIOLOGY_SCIENCES));
        courses.add(new Course("高等数学", MajorType.MATH));
        courses.add(new Course("宏观经济学", MajorType.FINANCE));
        courses.add(new Course("中国通史", MajorType.HISTORY));

        return courses;
    }
}

/**
 * 专业类型枚举
 */
enum MajorType {

    COMPUTER_SCIENCES("计算机科学与技术"), 
    BIOLOGY_SCIENCES("生物科学"), 
    MATH("数学"), 
    FINANCE("金融"), 
    HISTORY("历史"), 
    ALL("所有");

    private String name;

    MajorType(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

/**
 * 课程
 */
class Course {

    /**
     * 课程名
     */
    private final String name;

    /**
     * 专业类型
     */
    private final MajorType majorType;

    public Course(String name, MajorType majorType) {
        this.name = name;
        this.majorType = majorType;
    }

    public String getName() {
        return name;
    }

    public MajorType getMajorType() {
        return majorType;
    }

    @Override
    public String toString() {
        return "Course{" +
                "name='" + name + '\'' +
                ", majorType=" + majorType.getName() +
                '}';
    }
}

/**
 * 课程集合接口
 */
interface CourseCollection {

    /**
     * 添加
     *
     * @param course 课程
     */
    void add(Course course);

    /**
     * 删除
     *
     * @param course 课程
     */
    void remove(Course course);

    /**
     * 遍历
     *
     * @param majorType 专业类型
     * @return 课程迭代器
     */
    CourseIterator iterator(MajorType majorType);
}

/**
 * 课程迭代器接口
 */
interface CourseIterator {

    /**
     * 是否有下一个
     *
     * @return 存在下一个 : true
     */
    Boolean hasNext();

    /**
     * 下一个
     *
     * @return 课程对象
     */
    Course next();
}

/**
 * 课程集合接口实现类
 */
class CourseCollectionImpl implements CourseCollection {

    private final List<Course> courses;

    public CourseCollectionImpl() {
        courses = new ArrayList<>();
    }

    @Override
    public void add(Course course) {
        courses.add(course);
    }

    @Override
    public void remove(Course course) {
        courses.remove(course);
    }

    @Override
    public CourseIterator iterator(MajorType majorType) {

        return new CourserIteratorImpl(majorType, courses);
    }
}

/**
 * 课程迭代器接口实现类
 */
class CourserIteratorImpl implements CourseIterator {

    private final MajorType majorType;

    private final List<Course> courses;

    private int position;

    public CourserIteratorImpl(MajorType majorType, List<Course> courses) {
        this.majorType = majorType;
        this.courses = courses;
    }

    @Override
    public Boolean hasNext() {
        while (position < courses.size()) {
            Course course = courses.get(position);

            if (course.getMajorType().equals(majorType) || majorType.equals(MajorType.ALL)) {

                return true;

            } else {
                position++;
            }
        }

        return false;
    }

    @Override
    public Course next() {
        Course course = courses.get(position);
        position++;
        return course;
    }
}
  1. Iterator(课程迭代器接口):声明遍历集合所需的操作。
  2. 具体迭代器(课程迭代器实现类):实现遍历集合的特定算法,迭代器对象必须跟踪自身的遍历进度(使用Position记录)。这使得多个迭代器可以相互独立地遍历同一个集合。
  3. Collection(课程集合接口):声明一个或多个方法来获取与集合兼容的迭代器。返回的方法必须声明为迭代器接口,故:具体集合可以返回不同种类的迭代器。
  4. 具体集合(课程集合实现类):当客户端调用迭代器方式时,返回一个具体的迭代器对象。
  5. 客户端:通过集合和迭代器的接口与两者进行交互。客户端无需与具体类相耦合,允许同一客户端代码使用不同的集合和迭代器。
    • 客户端通常不会自行创建迭代器,而是直接从集合中获取。若客户端想要自定义迭代器时,才需要创建。

应用场景

  1. 当集合底层的数据结构较为复杂时,若希望对外部隐藏内部的复杂性时,可以使用迭代器模式。
    • 封装复杂数据结构的交互细节,为客户端提供访问元素的简单方法。这样对调用者友好,且能避免调用者在直接与集合交互时执行错误的操作,起到保护类的作用,也提升了代码的稳定性。
  2. 希望集合有多种遍历方式时,可以使用迭代器模式。
  3. 项目中存在大量遍历代码时,可以考虑使用迭代器模式简化。
    • 当业务逻辑中存在大量的遍历代码时,会让原有方法的职责变的模糊,降低可维护性;将遍历代码抽离到特定的迭代器中会让原有的方法更精炼,也更简洁。
  4. 若希望能遍历不同,甚至无法预知数据结构的集合时,可以使用迭代器模式。
    • 迭代器提供了一组公共的接口用于集合对象的访问。

优缺点

  • 优点:
    • 分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明的访问集合内部的数据。满足单一职责的原则。
    • 在原有代码的基础上,创建新的集合或迭代器时无需修改已有的代码;满足开闭原则。
    • 可以并行遍历同一集合,每个迭代器对象都包含其自身的遍历状态。
    • 可以暂停遍历过程,并在需要时恢复遍历。
  • 缺点:
    • 如果只是简单的遍历,迭代器会让原有的操作变的复杂。
    • 对于特殊的集合,使用迭代器进行遍历效率可能无法保证。

在 Java 中的应用

Java核心库为例:

  • java.util.Iterator
  • java.util.Scanner
  • java.util.Enumeration