迭代器模式

迭代器模式:统一集合遍历的设计艺术

一、迭代器模式的定义与核心思想

迭代器模式(Iterator Pattern) 是一种行为型设计模式,它提供一种方法顺序访问一个聚合对象(如集合、容器)中的各个元素,而无需暴露该对象的内部表示。其核心思想是 “分离集合的遍历逻辑与集合本身”,通过引入独立的迭代器对象,封装遍历细节,让集合类专注于元素的存储与管理,迭代器专注于元素的访问顺序控制。

简单来说,迭代器模式解决了 “如何不暴露集合内部结构,同时提供统一遍历方式” 的问题。例如,Java 中的 Iterator 接口、Python 中的 for...in 循环底层,都采用了迭代器模式的设计思想。

二、迭代器模式的角色构成

迭代器模式通常包含以下 4 个核心角色,各角色职责明确、分工协作:

角色名称 核心职责 示例(Java 场景)
抽象聚合类(Aggregate) 定义创建迭代器对象的接口,声明集合的基本操作(如添加、删除元素) List 接口
具体聚合类(ConcreteAggregate) 实现抽象聚合类,存储元素集合,并重写创建迭代器的方法,返回对应具体迭代器实例 ArrayList
抽象迭代器(Iterator) 定义遍历元素的接口,包含核心方法:hasNext()(判断是否有下一个元素)、next()(获取下一个元素) Iterator 接口
具体迭代器(ConcreteIterator) 实现抽象迭代器接口,记录当前遍历位置,封装具体的遍历逻辑(如顺序、逆序) ArrayList 内部的 Itr

三、迭代器模式的工作原理与实现示例

1. 工作流程

  1. 客户端请求具体聚合类创建迭代器实例;

  2. 客户端通过迭代器的 hasNext() 方法判断是否还有未遍历的元素;

  3. 若有,通过 next() 方法获取下一个元素并进行处理;

  4. 重复步骤 2-3,直至遍历完所有元素。

2. 代码实现(Java 示例)

以 “图书集合” 为例,实现一个支持顺序遍历的迭代器模式:

(1)抽象迭代器接口(Iterator)
// 抽象迭代器:定义遍历接口

public interface BookIterator {

   boolean hasNext(); // 判断是否有下一本书

   Book next(); // 获取下一本书

}
(2)抽象聚合类(Aggregate)
// 抽象聚合类:定义集合操作与创建迭代器的接口

public interface BookCollection {

   void addBook(Book book); // 添加图书

   void removeBook(Book book); // 删除图书

   BookIterator createIterator(); // 创建迭代器

}
(3)具体元素类(Book)
// 集合中的元素:图书类

public class Book {

   private String name; // 书名

   private String author; // 作者

   public Book(String name, String author) {

       this.name = name;

       this.author = author;

   }

   // getter/setter 省略

   @Override

   public String toString() {

       return "《" + name + "》(作者:" + author + ")";

   }

}
(4)具体聚合类(ConcreteAggregate)
// 具体聚合类:图书集合(基于数组存储)

public class ConcreteBookCollection implements BookCollection {

   private Book[] books;

   private int size = 0; // 当前图书数量

   private static final int DEFAULT_CAPACITY = 10; // 默认容量

   public ConcreteBookCollection() {

       this.books = new Book[DEFAULT_CAPACITY];

   }

   @Override

   public void addBook(Book book) {

       if (size >= books.length) {

           // 扩容逻辑(简化实现)

           Book[] newBooks = new Book[books.length * 2];

           System.arraycopy(books, 0, newBooks, 0, books.length);

           books = newBooks;

       }

       books[size++] = book;

   }

   @Override

   public void removeBook(Book book) {

       for (int i = 0;i<books.length;i ++) {

           if (books[i].equals(book)) {

               // 移除元素:后续元素前移

               System.arraycopy(books, i+1, books, i, size - i - 1);

               books[--size] = null;

               break;

           }

       }

   }

   @Override

   public BookIterator createIterator() {

       // 返回具体迭代器,传入当前集合的元素数组和大小

       return new ConcreteBookIterator(books, size);

   }

}
(5)具体迭代器类(ConcreteIterator)
// 具体迭代器:实现图书集合的顺序遍历
public class ConcreteBookIterator implements BookIterator {
    private Book[] books;
    private int size;
    private int currentIndex = 0; // 当前遍历索引

    public ConcreteBookIterator(Book[] books, int size) {
        this.books = books;
        this.size = size;
    }

    @Override
    public boolean hasNext() {
        // 条件:1. 当前索引未超出集合实际大小 2. 当前位置元素不为空
        return currentIndex < size && books[currentIndex] != null;
    }

    @Override
    public Book next() {
        if (!hasNext()) {
            throw new NoSuchElementException("没有更多图书了");
        }
        return books[currentIndex++]; // 返回当前元素并移动索引
    }
}
(6)客户端调用示例
public class Client {

   public static void main(String[] args) {

       // 1. 创建具体聚合对象(图书集合)

       BookCollection bookCollection = new ConcreteBookCollection();

       // 2. 向集合添加元素

       bookCollection.addBook(new Book("设计模式", " Erich Gamma"));

       bookCollection.addBook(new Book("Java编程思想", "Bruce Eckel"));

       bookCollection.addBook(new Book("深入理解Java虚拟机", "周志明"));

       // 3. 获取迭代器并遍历

       BookIterator iterator = bookCollection.createIterator();

       System.out.println("图书列表:");

       while (iterator.hasNext()) {

           Book book = iterator.next();

           System.out.println(book);

       }

   }

}
输出结果
图书列表:

《设计模式》(作者:Erich Gamma)

《Java编程思想》(作者:Bruce Eckel)

《深入理解Java虚拟机》(作者:周志明)

四、迭代器模式的应用场景

迭代器模式适用于以下场景:

  1. 需要统一遍历不同结构的集合:例如,无论集合是数组、链表、哈希表,都通过相同的 hasNext()/next() 方法遍历,降低客户端学习成本。

  2. 不希望暴露集合内部实现:客户端无需知道集合是基于数组还是链表存储,只需通过迭代器访问元素,符合 “封装” 原则。

  3. 需要灵活切换遍历方式:例如,同一集合可支持顺序遍历、逆序遍历、过滤遍历(如只遍历偶数元素),只需创建不同的具体迭代器即可。

  4. 集合类职责单一:集合类仅负责元素的增删改查,遍历逻辑交给迭代器,符合 “单一职责原则”。

五、迭代器模式的优缺点

优点

  1. 解耦遍历与集合:遍历逻辑独立于集合,集合修改(如更换存储结构)时,无需修改客户端遍历代码。

  2. 统一遍历接口:不同集合的遍历方式标准化,客户端代码更简洁、易维护。

  3. 支持多种遍历方式:可通过扩展具体迭代器,实现同一集合的不同遍历逻辑(如顺序、逆序、过滤)。

  4. 符合设计原则:遵循 “单一职责原则”(集合管存储,迭代器管遍历)和 “开闭原则”(新增遍历方式无需修改原有代码)。

缺点

  1. 增加类的数量:每新增一个集合类,可能需要对应新增一个迭代器类,增加了系统的复杂性。

  2. 遍历过程中修改集合需谨慎:若遍历过程中对集合进行增删操作,可能导致迭代器状态混乱(如漏遍历、重复遍历),需额外处理并发问题(如快速失败机制)。

  3. 简单集合场景下冗余:对于结构简单的集合(如固定大小的数组),直接遍历可能比引入迭代器更高效。

posted @ 2025-12-08 22:31  圣祖帝皇  阅读(31)  评论(0)    收藏  举报