概述:迭代器模式 ∈ 行为型模式
模式定义
- 迭代器模式提供了一种统一访问集合对象元素的方式,将遍历操作封装到迭代器中,简化集合接口、并解耦集合与遍历操作。
- 迭代器模式是一种行为型设计模式
- 它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。
简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。
模式的组成
- 抽象的集合迭代器(Iterator):定义了遍历聚合对象所需的方法,包括hashNext()和next()方法等,用于遍历聚合对象中的元素。
- 具体的集合迭代器(Concrete Iterator):它是实现迭代器接口的具体实现类,负责具体的遍历逻辑。
它保存了当前遍历的位置信息,并可以根据需要向前或向后遍历集合元素。
- 抽象的聚合器(Aggregate): 一般是一个接口,提供一个iterator()方法
例如: java中的Collection接口,List接口,Set接口等。
- 具体的聚合器(Concrete Aggregate):就是抽象容器的具体实现类
比如: List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。
模式特点
优点
- 简化了集合类的接口,使用者可以更加简单地遍历集合对象,而不需要了解集合内部结构和实现细节。
- 将集合和遍历操作解耦,使得我们可以更灵活地使用不同的迭代器来遍历同一个集合,根据需求选择不同的遍历方式。
- 满足开闭原则,如果需要增加新的遍历方式,只需实现一个新的具体迭代器即可,不需要修改原先聚合对象的代码。
缺点
- 具体迭代器实现的算法对外不可见,因此不利于调试和维护。
- 对于某些小型、简单的集合对象来说,使用迭代器模式可能会显得过于复杂,增加了代码的复杂性。
案例实践
CASE 生活场景-教师按照班级名单点名
- 遍历班级名单:假设你是一名班主任,你需要遍历班级名单来点名。
班级名单可以看作是一个集合,每个学生名字可以看作是集合中的一个元素。
使用迭代器模式,你可以通过迭代器对象逐个访问学生的名字,而不需要了解班级名单的具体实现细节。
Student : 被遍历的数据对象
- import lombok.Data;
- import lombok.ToString;
- /**
- * 学生实体类
- */
- @Data
- @ToString
- public class Student {
- private String name;
- private Integer age;
- public Student(String name,Integer age){
- this.age=age;
- this.name=name;
- }
- }
复制代码 StudentCollectionIterator : 抽象的集合迭代器
创建一个抽象迭代器(学生迭代器)并继承Iterator接口(java.util包下的Iterator)
- StudentCollectionIterator
- import java.util.Iterator;
- /**
- * 抽象的集合迭代器(Iterator):学生集合的迭代器
- * 实现Iterator接口
- * 负责定义访问和遍历元素的接口,例如提供hasNext()和next()方法。
- */
- public interface StudentCollectionIterator extends Iterator<Student> {
- }
复制代码 [code]package java.util;import java.util.function.Consumer;/** * 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: * *
*
- Iterators allow the caller to remove elements from the * underlying collection during the iteration with well-defined * semantics. * Method names have been improved. *
* *
This interface is a member of the * * Java Collections Framework. * * @param the type of elements returned by this iterator * * @author Josh Bloch * @see Collection * @see ListIterator * @see Iterable * @since 1.2 */public interface Iterator { /** * 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(); /** * Removes from the underlying collection the last element returned * by this iterator (optional operation). This method can be called * only once per call to {@link #next}. The behavior of an iterator * is unspecified if the underlying collection is modified while the * iteration is in progress in any way other than by calling this * method. * * @implSpec * The default implementation throws an instance of * {@link UnsupportedOperationException} and performs no other action. * * @throws UnsupportedOperationException if the {@code remove} * operation is not supported by this iterator * * @throws IllegalStateException if the {@code next} method has not * yet been called, or the {@code remove} method has already * been called after the last call to the {@code next} * method */ default void remove() { throw new UnsupportedOperationException("remove"); } /** * Performs the given action for each remaining element until all elements * have been processed or the action throws an exception. Actions are * performed in the order of iteration, if that order is specified. * Exceptions thrown by the action are relayed to the caller. * * @implSpec *
The default implementation behaves as if: * {@code * while (hasNext()) * action.accept(next()); * } * * @param action The action to be performed for each element * @throws NullPointerException if the specified action is null * @since 1.8 */ default void forEachRemaining(Consumer |