rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • 迭代器模式(Iterator Pattern)

  • 一、定义
  • 二、意图
  • 三、结构
  • 四、优点
  • 五、缺点
  • 六、类图(Mermaid)
  • 七、时序图(Mermaid)
  • 八、适用环境
  • 九、模式分析
  • 十、模式扩展
  • 十一、模式应用
  • 十二、Android 中的应用
  • 十三、代码实现(Java 版)
    • 1. 抽象迭代器(Iterator)
    • 2. 抽象聚合(Aggregate)
    • 3. 具体元素(Book)
    • 4. 具体聚合(BookShelf)
    • 5. 具体迭代器(BookShelfIterator)
    • 6. 客户端(Client)
    • 7. 运行结果
  • 十四、总结

迭代器模式(Iterator Pattern)

迭代器模式是一种行为型设计模式,它提供了一种统一的方法来顺序访问聚合对象(如集合、容器)中的元素,而无需暴露聚合对象的内部结构。这种模式将 “遍历元素” 的行为与 “存储元素” 的聚合对象分离,使得遍历逻辑可以独立于聚合结构变化。

一、定义

官方定义:提供一种方法访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

通俗理解:迭代器模式就像一本书的目录 —— 读者无需知道书的内页是如何装订的(内部结构),只需通过目录(迭代器)按顺序翻阅每一页(元素)。例如,Java 中的 Iterator 就是迭代器模式的典型实现,无论集合是 ArrayList(数组结构)还是 LinkedList(链表结构),都可以通过 Iterator 统一遍历。

二、意图

  1. 解耦聚合与遍历:让聚合对象(如集合)专注于存储数据,将遍历元素的逻辑交给迭代器,两者独立变化。
  2. 统一遍历接口:为不同结构的聚合对象提供一致的遍历方式(如 hasNext()、next()),简化客户端使用。
  3. 支持多种遍历方式:一个聚合对象可以有多个迭代器,分别实现不同的遍历逻辑(如正向遍历、反向遍历、过滤遍历)。
  4. 隐藏内部结构:客户端无需知道聚合对象的内部实现(如数组、链表、树),只需通过迭代器访问元素。

三、结构

迭代器模式包含4 个核心角色,各角色协同实现 “存储” 与 “遍历” 的分离:

角色名称核心职责
抽象迭代器(Iterator)定义遍历元素的接口,通常包含: - hasNext():判断是否还有下一个元素; - next():获取下一个元素; - (可选)remove():移除当前元素。
具体迭代器(ConcreteIterator)实现抽象迭代器接口,持有聚合对象的引用,记录当前遍历位置,完成实际的遍历逻辑。
抽象聚合(Aggregate)定义创建迭代器的接口(如 createIterator()),是聚合对象的抽象表示。
具体聚合(ConcreteAggregate)实现抽象聚合接口,存储元素,返回具体迭代器实例(与自身匹配的迭代器)。

四、优点

  1. 分离职责:聚合对象负责存储数据,迭代器负责遍历数据,符合 “单一职责原则”。
  2. 统一接口:不同结构的聚合对象(数组、链表、树)可通过相同的迭代器接口遍历,简化客户端代码。
  3. 支持多遍历:一个聚合对象可创建多个不同的迭代器,实现多种遍历方式(如正向、反向、过滤)。
  4. 隐藏内部结构:客户端无需了解聚合对象的内部实现(如 ArrayList 的数组、LinkedList 的链表),降低耦合。
  5. 便于扩展:新增聚合类型时,只需实现对应的迭代器;新增遍历方式时,只需新增迭代器,符合 “开闭原则”。

五、缺点

  1. 类数量增加:每个聚合对象可能需要对应一个迭代器,导致系统中类的数量增加,增加维护成本。
  2. 迭代器与聚合耦合:具体迭代器依赖于具体聚合的内部结构(如迭代器需要知道聚合是数组还是链表),两者耦合度较高。
  3. 简单场景冗余:对于简单的聚合对象(如固定大小的数组),直接遍历可能比使用迭代器更简洁,此时使用迭代器模式会显得过度设计。
  4. 并发问题:若聚合对象在迭代过程中被修改(如添加 / 删除元素),迭代器可能会出现异常(如 Java 的 ConcurrentModificationException)。

六、类图(Mermaid)

以 “书架(BookShelf)存储书籍(Book)” 为例,类图展示迭代器模式的结构:

classDiagram
    direction TB
    class Iterator {
        <<interface>>
        +hasNext(): boolean
        +next(): Object
    }
    
    class BookShelfIterator {
        -bookShelf: BookShelf
        -index: int
        +BookShelfIterator(bookShelf: BookShelf)
        +hasNext(): boolean
        +next(): Book
    }
    
    class Aggregate {
        <<interface>>
        +createIterator(): Iterator
    }
    
    class BookShelf {
        -books: Book[]
        -size: int
        +BookShelf(maxSize: int)
        +addBook(book: Book): void
        +getBookAt(index: int): Book
        +getSize(): int
        +createIterator(): Iterator
    }
    
    class Book {
        -name: String
        +Book(name: String)
        +getName(): String
    }
    
    class Client {
        +main(): void
    }
    
    Iterator <|.. BookShelfIterator
    Aggregate <|.. BookShelf
    BookShelfIterator o-- BookShelf : "持有"
    BookShelf o-- Book : "包含"
    Client --> BookShelf : "创建并使用"
    Client --> Iterator : "通过迭代器遍历"

七、时序图(Mermaid)

以下时序图展示客户端通过迭代器遍历书架中书籍的过程:

sequenceDiagram
    participant Client
    participant BookShelf as 具体聚合(书架)
    participant BookShelfIterator as 具体迭代器
    participant Book as 书籍(元素)
    
    %% 1. 客户端创建聚合对象并添加元素
    Client->>BookShelf: 1. 创建书架(new BookShelf(3))
    Client->>Book: 2. 创建书籍1(《设计模式》)
    Client->>BookShelf: 3. 添加书籍1(addBook(book1))
    Client->>Book: 4. 创建书籍2(《Java编程》)
    Client->>BookShelf: 5. 添加书籍2(addBook(book2))
    
    %% 2. 客户端获取迭代器
    Client->>BookShelf: 6. 获取迭代器(createIterator())
    BookShelf->>BookShelfIterator: 7. 创建迭代器(new BookShelfIterator(this))
    BookShelfIterator-->>BookShelf: 8. 返回迭代器实例
    BookShelf-->>Client: 9. 返回迭代器给客户端
    
    %% 3. 客户端通过迭代器遍历元素
    loop 遍历所有书籍
        Client->>BookShelfIterator: 10. 调用 hasNext()
        BookShelfIterator-->>Client: 11. 返回 true(还有下一本书)
        Client->>BookShelfIterator: 12. 调用 next()
        BookShelfIterator->>BookShelf: 13. 获取当前书籍(getBookAt(index))
        BookShelf->>Book: 14. 返回书籍对象
        Book-->>BookShelfIterator: 15. 返回书籍
        BookShelfIterator-->>Client: 16. 返回书籍给客户端
        Client->>Book: 17. 打印书籍名称(getName())
    end
    
    Client->>BookShelfIterator: 18. 再次调用 hasNext()
    BookShelfIterator-->>Client: 19. 返回 false(无更多书籍)

八、适用环境

当系统满足以下场景时,适合使用迭代器模式:

  1. 需要遍历聚合对象,但不希望暴露其内部结构:如封装自定义集合(如树形结构、图结构),隐藏实现细节。
  2. 需要统一不同聚合对象的遍历接口:如同时使用数组、链表、哈希表时,通过相同的迭代器接口遍历。
  3. 需要多种遍历方式:如对一个集合同时需要正向遍历、反向遍历、按条件过滤遍历。
  4. 聚合对象的内部结构可能变化:通过迭代器隔离遍历逻辑,当聚合内部结构改变时,只需修改迭代器,无需修改客户端。

九、模式分析

  1. 核心逻辑:迭代器模式的本质是 “封装遍历”—— 将遍历元素的逻辑从聚合对象中抽离,形成独立的迭代器对象,使两者可以独立演化。
  2. 迭代器的类型:
    • 内部迭代器:迭代器控制遍历过程(如 Java 8 的 forEach),客户端只需提供处理逻辑,无需关心遍历步骤。
    • 外部迭代器:客户端控制遍历过程(如 Java 的 Iterator),通过 hasNext() 和 next() 手动推进遍历,灵活性更高。
  3. 与集合的关系:迭代器是集合的 “访问接口”,集合必须提供创建迭代器的方法;迭代器依赖集合的内部结构才能正确遍历(如数组的索引、链表的指针)。
  4. 删除元素的注意事项:迭代器的 remove() 方法需谨慎实现,需确保删除后不影响后续遍历(如 Java 迭代器的 remove() 必须在 next() 之后调用)。

十、模式扩展

迭代器模式可根据业务需求扩展出多种变体:

  1. 双向迭代器(Bidirectional Iterator):支持向前和向后遍历,增加 hasPrevious() 和 previous() 方法(如 Java 的 ListIterator)。
  2. 跳跃迭代器(Jump Iterator):支持跳过指定数量的元素(如 skip(n) 方法),适用于大数据集的快速定位。
  3. 过滤迭代器(Filter Iterator):遍历过程中只返回符合条件的元素(如 next(predicate),只返回满足 predicate 的元素)。
  4. 懒加载迭代器(Lazy Iterator):按需加载元素(如分页查询时,只在调用 next() 时才加载下一页数据),减少内存占用。
  5. 并发迭代器(Concurrent Iterator):支持在迭代过程中安全修改聚合对象(如采用快照机制,避免 ConcurrentModificationException)。

十一、模式应用

迭代器模式是编程语言和框架中最常用的设计模式之一,典型应用包括:

  1. 编程语言集合框架:
    • Java:java.util.Iterator 接口(ArrayList、HashMap 等集合的迭代器实现)。
    • C#:IEnumerator 接口(List、Dictionary 等的迭代器)。
    • Python:迭代器协议(__iter__() 和 __next__() 方法),支持 for 循环遍历。
    • C++:STL 中的 iterator(如 vector::iterator、list::iterator)。
  2. 数据库查询结果遍历:
    • JDBC 的 ResultSet:通过 next() 方法遍历查询结果,本质是迭代器模式。
    • Android 的 Cursor:遍历数据库查询结果,moveToNext() 类似 hasNext() + next()。
  3. 自定义集合遍历:
    • 树形结构(如二叉树)的迭代器(前序、中序、后序遍历)。
    • 图结构的迭代器(深度优先、广度优先遍历)。

十二、Android 中的应用

在 Android 开发中,迭代器模式的应用广泛,以下是典型场景:

  1. Java 集合框架的应用: Android 基于 Java 生态,直接使用 Java 集合框架的迭代器,如:

    List<String> list = new ArrayList<>();
    // 添加元素...
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String item = iterator.next();
        // 处理元素
    }
    
  2. Cursor 遍历数据库结果: 查询 SQLite 数据库时,Cursor 扮演迭代器角色,遍历查询结果:

    Cursor cursor = db.query("users", null, null, null, null, null, null);
    while (cursor.moveToNext()) { // 类似 hasNext() + next()
        String name = cursor.getString(cursor.getColumnIndex("name"));
        // 处理数据
    }
    cursor.close();
    
  3. RecyclerView 数据遍历: RecyclerView.Adapter 中的数据遍历逻辑本质上依赖迭代器思想,getItemCount() 和 onBindViewHolder() 配合完成数据到视图的映射,相当于 “隐式迭代器”。

  4. 自定义集合迭代: 开发中若需自定义数据结构(如树形菜单、多级列表),可通过迭代器模式封装遍历逻辑,简化 UI 渲染代码。

十三、代码实现(Java 版)

以 “书架存储书籍” 为例,实现迭代器模式,支持正向遍历书籍:

1. 抽象迭代器(Iterator)

// 抽象迭代器:定义遍历接口
public interface Iterator {
    // 判断是否有下一个元素
    boolean hasNext();
    // 获取下一个元素
    Object next();
}

2. 抽象聚合(Aggregate)

// 抽象聚合:定义创建迭代器的接口
public interface Aggregate {
    Iterator createIterator();
}

3. 具体元素(Book)

// 具体元素:书籍
public class Book {
    private String name; // 书名

    public Book(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

4. 具体聚合(BookShelf)

// 具体聚合:书架(存储书籍)
public class BookShelf implements Aggregate {
    private Book[] books; // 用数组存储书籍(内部结构)
    private int size; // 当前书籍数量

    // 初始化书架容量
    public BookShelf(int maxSize) {
        this.books = new Book[maxSize];
        this.size = 0;
    }

    // 添加书籍
    public void addBook(Book book) {
        if (size < books.length) {
            books[size] = book;
            size++;
        } else {
            System.out.println("书架已满,无法添加书籍:" + book.getName());
        }
    }

    // 获取指定位置的书籍(供迭代器使用)
    public Book getBookAt(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引越界:" + index);
        }
        return books[index];
    }

    // 获取书籍数量
    public int getSize() {
        return size;
    }

    // 创建并返回迭代器
    @Override
    public Iterator createIterator() {
        return new BookShelfIterator(this);
    }
}

5. 具体迭代器(BookShelfIterator)

// 具体迭代器:书架迭代器(遍历书籍)
public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf; // 持有书架引用
    private int index; // 当前遍历位置

    // 初始化迭代器,从第0个元素开始
    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    // 判断是否还有下一本书
    @Override
    public boolean hasNext() {
        return index < bookShelf.getSize();
    }

    // 获取下一本书,并移动索引
    @Override
    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

6. 客户端(Client)

// 客户端:使用迭代器遍历书架
public class Client {
    public static void main(String[] args) {
        // 1. 创建书架(容量为3)
        BookShelf bookShelf = new BookShelf(3);

        // 2. 向书架添加书籍
        bookShelf.addBook(new Book("《设计模式:可复用面向对象软件的基础》"));
        bookShelf.addBook(new Book("《Java编程思想》"));
        bookShelf.addBook(new Book("《Android开发艺术探索》"));
        bookShelf.addBook(new Book("《多余的书》")); // 书架已满,添加失败

        // 3. 获取迭代器并遍历
        Iterator iterator = bookShelf.createIterator();
        System.out.println("书架中的书籍:");
        while (iterator.hasNext()) {
            Book book = (Book) iterator.next();
            System.out.println("- " + book.getName());
        }
    }
}

7. 运行结果

书架已满,无法添加书籍:《多余的书》
书架中的书籍:
- 《设计模式:可复用面向对象软件的基础》
- 《Java编程思想》
- 《Android开发艺术探索》

十四、总结

迭代器模式通过分离 “聚合对象” 与 “遍历逻辑”,提供了一种统一、灵活的元素访问方式,其核心价值在于:

  1. 解耦存储与遍历:聚合对象专注于数据存储,迭代器专注于遍历逻辑,两者独立演化,降低耦合。
  2. 统一遍历接口:无论聚合内部是数组、链表还是其他结构,客户端都可通过相同的迭代器接口访问,简化使用。
  3. 支持多维度扩展:新增聚合类型只需实现对应的迭代器;新增遍历方式只需新增迭代器,符合 “开闭原则”。

在实际开发中,迭代器模式已被编程语言的集合框架广泛采用(如 Java 的 Iterator),开发者无需重复实现基础迭代逻辑。但在自定义复杂数据结构(如树、图)时,手动实现迭代器模式能有效隐藏内部结构,简化遍历逻辑。

需注意避免过度设计:对于简单聚合(如固定大小的数组),直接遍历可能更简洁;同时需处理迭代过程中聚合对象的修改问题(如采用快速失败机制)。

总之,迭代器模式是 “封装变化” 思想的典型体现,是处理集合遍历问题的标准解决方案。

最近更新:: 2025/10/22 15:36
Contributors: 罗凯文, luokaiwen