【设计模式】【行为型模式】迭代器模式(Iterator)

👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD

🔥 2025本人正在沉淀中... 博客更新速度++

👍 欢迎点赞、收藏、关注,跟上我的更新节奏

🎵 当你的天空突然下了大雨,那是我在为你炸乌云

文章目录

一、入门

什么是迭代器模式?

迭代器模式(Iterator Pattern)是一种行为设计模式,它提供了一种顺序访问聚合对象中元素的方法,而不需要暴露其底层表示。迭代器模式将遍历逻辑从聚合对象中分离出来,使得聚合对象可以专注于数据存储,而迭代器负责遍历。

为什么要迭代器模式?

在没有迭代器模式的情况下,客户端代码需要直接依赖书架的内部结构(如数组或列表)来遍历书籍。这种方式会导致遍历逻辑与书架类耦合。

java 复制代码
// 书籍类
class Book {
    private String name;

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

    public String getName() {
        return name;
    }
}

// 书架类
class BookShelf {
    private Book[] books;
    private int size;

    public BookShelf(int capacity) {
        books = new Book[capacity];
        size = 0;
    }

    public void addBook(Book book) {
        if (size < books.length) {
            books[size++] = book;
        }
    }

    // 暴露内部数组
    public Book[] getBooks() {
        return books;
    }

    // 暴露书架大小
    public int getSize() {
        return size;
    }
}

// 客户端代码
public class LibraryWithoutIterator {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(3);
        bookShelf.addBook(new Book("Design Patterns"));
        bookShelf.addBook(new Book("Clean Code"));
        bookShelf.addBook(new Book("Refactoring"));

        // 直接依赖书架的内部结构(数组)进行遍历
        Book[] books = bookShelf.getBooks();
        for (int i = 0; i < bookShelf.getSize(); i++) {
            System.out.println(books[i].getName());
        }
    }
}

存在的问题

  1. 耦合性强:客户端代码直接依赖书架的内部结构(数组),如果书架的存储结构改为链表,客户端代码也需要修改。
  2. 破坏封装性:书架类暴露了内部数据(数组和大小),客户端代码可以直接操作这些数据,可能导致数据不一致。
  3. 无法统一遍历接口:如果图书馆中有多种存储结构(如书架、电子书库等),客户端代码需要为每种结构编写特定的遍历逻辑。

怎么实现迭代器模式?

迭代器模式的组成

  1. 迭代器接口(Iterator Interface) :定义了遍历元素所需的操作,如next()hasNext()等。
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,负责管理当前遍历的位置。
  3. 聚合接口(Aggregate Interface) :定义了创建迭代器的方法,如createIterator()
  4. 具体聚合类(Concrete Aggregate):实现聚合接口,返回一个具体迭代器的实例。

【案例】图书管理 - 改

迭代器接口(Iterator Interface)Iterator迭代器接口,定义遍历聚合对象所需的方法。

java 复制代码
interface Iterator<T> {
    boolean hasNext();
    T next();
}
具体迭代器(Concrete Iterator):BookShelfIterator 类,实现迭代器接口,负责管理当前遍历的位置,并实现具体的遍历逻辑。
// 具体迭代器
class BookShelfIterator implements Iterator<Book> {
    private BookShelf bookShelf; // 关联的具体聚合类
    private int currentIndex = 0; // 当前遍历的位置

    // 构造函数,传入具体聚合类
    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
    }

    @Override
    public boolean hasNext() {
        return currentIndex < bookShelf.getSize(); // 判断是否还有下一个元素
    }

    @Override
    public Book next() {
        Book book = bookShelf.getBookAt(currentIndex); // 获取当前元素
        currentIndex++; // 移动游标
        return book;
    }
}

聚合接口(Aggregate Interface) : Aggregate接口,定义创建迭代器的方法。

java 复制代码
// 聚合接口
interface Aggregate<T> {
    Iterator<T> createIterator(); // 创建迭代器
}
具体聚合类(Concrete Aggregate):BookShelf类,实现聚合接口,负责存储和管理数据,并提供创建迭代器的方法。
// 具体聚合类
class BookShelf implements Aggregate<Book> {
    private Book[] books; // 存储书籍的数组
    private int size;      // 当前书籍数量

    // 构造函数,初始化书架容量
    public BookShelf(int capacity) {
        books = new Book[capacity];
        size = 0;
    }

    // 添加书籍
    public void addBook(Book book) {
        if (size < books.length) {
            books[size++] = book;
        }
    }

    // 获取指定位置的书籍
    public Book getBookAt(int index) {
        return books[index];
    }

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

    // 实现聚合接口,创建迭代器
    @Override
    public Iterator<Book> createIterator() {
        return new BookShelfIterator(this); // 将当前书架对象传递给迭代器
    }
}

Book类

java 复制代码
class Book {
    private String name;

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

    public String getName() {
        return name;
    }
}

测试类

java 复制代码
// 客户端代码
public class LibraryDemo {
    public static void main(String[] args) {
        // 创建一个书架
        BookShelf bookShelf = new BookShelf(3);
        bookShelf.addBook(new Book("Design Patterns"));
        bookShelf.addBook(new Book("Clean Code"));
        bookShelf.addBook(new Book("Refactoring"));

        // 创建迭代器
        Iterator<Book> iterator = bookShelf.createIterator();

        // 使用迭代器遍历书架
        System.out.println("Books in BookShelf:");
        while (iterator.hasNext()) {
            Book book = iterator.next();
            System.out.println(book.getName());
        }
    }
}

输出结果

shell 复制代码
Books in BookShelf:
Design Patterns
Clean Code
Refactoring

二、迭代器模式在源码中的运用

Java 集合框架(Java Collections Framework)

Java集合框架迭代器的使用

Java 的集合框架(如 ArrayListLinkedListHashSet 等)广泛使用了迭代器模式。每个集合类都实现了 Iterable 接口,并提供了 iterator() 方法来返回一个迭代器。

java 复制代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JavaCollectionExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Cherry");

        // 使用迭代器遍历集合
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Java集合框架迭代器的源码实现

Iterable接口:定义了iterator()方法,用于返回一个迭代器。

java 复制代码
public interface Iterable<T> {
    Iterator<T> iterator();
}

Iterator接口:定义了遍历集合的方法,如hasNext()next()

java 复制代码
public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); // 可选操作
}

ArrayList中的迭代器实现:

java 复制代码
public Iterator<E> iterator() {
    return new Itr();
}

private class Itr implements Iterator<E> {
    int cursor;       // 当前遍历的位置
    int lastRet = -1; // 上一次返回的元素索引

    public boolean hasNext() {
        return cursor != size;
    }

    public E next() {
        // 返回当前元素,并移动游标
        // ...
    }

    public void remove() {
        // 删除上一次返回的元素
        // ...
    }
}

三、总结

迭代器模式的优点

  1. 解耦遍历逻辑与聚合对象
    • 将遍历逻辑从聚合对象中分离出来,聚合对象可以专注于数据存储,而迭代器负责遍历。
    • 符合单一职责原则。
  2. 统一遍历接口
    • 提供了一种统一的方式来遍历不同类型的聚合对象(如数组、链表、树等)。
    • 客户端代码无需关心聚合对象的内部结构。
  3. 支持多种遍历方式
    • 可以为同一个聚合对象定义多个迭代器,实现不同的遍历方式(如正序遍历、逆序遍历、深度优先遍历等)。
  4. 增强封装性
    • 隐藏了聚合对象的内部结构,客户端代码只能通过迭代器访问元素,无法直接操作聚合对象的内部数据。
  5. 开闭原则
    • 新增聚合类和迭代器类不会影响现有代码,易于扩展。

迭代器模式的缺点

  1. 增加复杂性
    • 对于简单的聚合对象,使用迭代器模式可能会增加代码复杂性。
    • 如果遍历逻辑非常简单,直接使用 for 循环可能更直观。
  2. 性能开销
    • 迭代器模式可能会引入额外的性能开销,尤其是在遍历大型数据集时。
  3. 不适合频繁修改的聚合对象
    • 如果聚合对象在遍历过程中频繁修改(如添加或删除元素),可能会导致迭代器失效或抛出异常。

迭代器模式的典型应用场景

  1. 集合框架
    • Java 的集合框架(如 ArrayList、LinkedList、HashSet 等)广泛使用了迭代器模式。
  2. 文件系统遍历
    • 遍历文件系统中的目录和文件时,可以使用迭代器模式封装遍历逻辑。
  3. 数据库查询结果遍历
    • 遍历数据库查询结果集时,可以使用迭代器模式提供统一的遍历接口。
  4. 树形结构遍历
    • 遍历树形结构(如 DOM 树、组织结构树等)时,可以使用迭代器模式支持多种遍历方式(如深度优先遍历、广度优先遍历等)。
相关推荐
shuair1 小时前
idea 2023.3.7常用插件
java·ide·intellij-idea
小安同学iter2 小时前
使用Maven将Web应用打包并部署到Tomcat服务器运行
java·tomcat·maven
Yvonne9782 小时前
创建三个节点
java·大数据
不会飞的小龙人3 小时前
Kafka消息服务之Java工具类
java·kafka·消息队列·mq
是小崔啊3 小时前
java网络编程02 - HTTP、HTTPS详解
java·网络·http
brevity_souls4 小时前
Spring Boot 内置工具类
java·spring boot
小钊(求职中)4 小时前
Java开发实习面试笔试题(含答案)
java·开发语言·spring boot·spring·面试·tomcat·maven
shix .4 小时前
什么是tomcat
java·tomcat
java技术小馆4 小时前
Deepseek整合SpringAI
java·spring cloud
天荒地老笑话么4 小时前
Mac安装配置Tomcat 8
java·macos·tomcat