迭代器模式:定义、结构、实现、优缺点、应用场景

迭代器模式,说白了就是提供一种统一的方式来遍历集合对象。你想想看,我们平时写代码,经常要遍历数组、列表、树、图这些数据结构。如果没有迭代器,每个集合都得自己暴露内部结构,那代码就乱套了。

我个人习惯把迭代器模式叫做"遍历的标准化接口"。它把遍历逻辑从集合中抽离出来,让客户端代码不用关心底层是数组还是链表,只管调用 next() 和 hasNext() 就行。

模式定义

迭代器模式(Iterator Pattern)属于行为型设计模式。它提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

嗯,这里要注意:核心思想就两点——分离遍历行为隐藏内部结构

模式结构

迭代器模式的结构其实很清晰,我画个图你就明白了:

迭代器模式结构图 «接口» Iterator + hasNext(): boolean + next(): Object + remove(): void ConcreteIterator - cursor: int + hasNext(): boolean «接口» Aggregate + createIterator(): Iterator ConcreteAggregate - items: List + createIterator(): Iterator 创建 Client

结构中的角色就四个:

  • Iterator(迭代器接口):定义 hasNext()、next() 等基本操作
  • ConcreteIterator(具体迭代器):实现遍历逻辑,维护当前游标位置
  • Aggregate(聚合接口):定义创建迭代器的方法
  • ConcreteAggregate(具体聚合):实现聚合接口,返回对应的迭代器实例

代码实现

我拿一个实际项目中的例子来说。之前我在做一个报表系统,需要遍历不同格式的数据源——有的来自数据库,有的来自内存缓存。用迭代器模式就特别合适。

// 迭代器接口
public interface Iterator<T> {
    boolean hasNext();
    T next();
    void remove();
}

// 具体迭代器 - 数组迭代器
public class ArrayIterator<T> implements Iterator<T> {
    private T[] items;
    private int cursor = 0;
    
    public ArrayIterator(T[] items) {
        this.items = items;
    }
    
    @Override
    public boolean hasNext() {
        return cursor < items.length;
    }
    
    @Override
    public T next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return items[cursor++];
    }
    
    @Override
    public void remove() {
        throw new UnsupportedOperationException("数组不支持删除");
    }
}

// 聚合接口
public interface Aggregate<T> {
    Iterator<T> createIterator();
}

// 具体聚合 - 数据集合
public class DataCollection<T> implements Aggregate<T> {
    private T[] items;
    
    public DataCollection(T[] items) {
        this.items = items;
    }
    
    @Override
    public Iterator<T> createIterator() {
        return new ArrayIterator<>(items);
    }
}

// 客户端使用
public class Client {
    public static void main(String[] args) {
        String[] data = {"A", "B", "C", "D"};
        DataCollection<String> collection = new DataCollection<>(data);
        Iterator<String> iterator = collection.createIterator();
        
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}
💡 我的小技巧:实际项目中,我习惯让迭代器支持"快速失败"(fail-fast)。就是在遍历过程中,如果集合被修改了,迭代器能立刻抛出异常。Java 的 ArrayList 就是这么干的。

优缺点分析

优点 缺点
  • 支持多种遍历方式(正序、逆序、过滤等)
  • 简化了聚合类的接口
  • 可以同时遍历同一个集合(多个迭代器互不干扰)
  • 符合开闭原则——新增遍历方式不用改聚合类
  • 增加了系统复杂度(多了一套类)
  • 对于简单集合,迭代器有点"杀鸡用牛刀"
  • 遍历过程中修改集合需要额外处理
⚠️ 避坑指南:我曾经在一个项目中,为了"优雅"给所有集合都套上了迭代器模式。结果发现有些集合就几个元素,用 for 循环三行搞定,硬生生写了两个类。后来我学乖了——迭代器模式适合复杂遍历或多种遍历方式,别为了用模式而用模式

应用场景

什么时候该用迭代器模式?我总结了几个典型场景:

  1. 需要多种遍历方式:比如既要正序遍历又要逆序遍历,还要按条件过滤
  2. 想隐藏集合内部结构:客户端不想知道底层是数组、链表还是树
  3. 需要统一遍历接口:不同数据源用同一套代码遍历
  4. 需要同时遍历多个集合:比如做数据对比、合并操作

举个实际例子。我之前做的一个日志分析系统,日志来源有文件、数据库、消息队列三种。每种来源的数据结构完全不同,但分析逻辑是一样的。我让它们都实现 Aggregate 接口,返回统一的迭代器。分析模块只需要写一套遍历代码,省了至少 40% 的重复工作。

📌 核心要点回顾:

  • 迭代器模式把遍历行为从集合中抽离出来
  • 核心接口就两个:hasNext() 和 next()
  • 适合复杂遍历场景,简单场景别硬用
  • Java、C#、Python 等语言已经内置了迭代器支持

其实现在很多语言都内置了迭代器。比如 Java 的 Iterable 接口、Python 的 __iter__ 和 __next__、C# 的 IEnumerable。但理解它的设计思想更重要——分离关注点,让遍历变得可扩展、可复用。这就是迭代器模式的价值所在。


公众号:蓝海资料掘金营,微信deep3321