👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD
🔥 2025本人正在沉淀中... 博客更新速度++
👍 欢迎点赞、收藏、关注,跟上我的更新节奏
🎵 当你的天空突然下了大雨,那是我在为你炸乌云
文章目录
- 一、入门
- 二、迭代器模式在源码中的运用
- [Java 集合框架(Java Collections Framework)](#Java 集合框架(Java Collections Framework))
- 三、总结
一、入门
什么是迭代器模式?
迭代器模式(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());
}
}
}
存在的问题
- 耦合性强:客户端代码直接依赖书架的内部结构(数组),如果书架的存储结构改为链表,客户端代码也需要修改。
- 破坏封装性:书架类暴露了内部数据(数组和大小),客户端代码可以直接操作这些数据,可能导致数据不一致。
- 无法统一遍历接口:如果图书馆中有多种存储结构(如书架、电子书库等),客户端代码需要为每种结构编写特定的遍历逻辑。
怎么实现迭代器模式?
迭代器模式的组成:
- 迭代器接口(Iterator Interface) :定义了遍历元素所需的操作,如
next()
、hasNext()
等。 - 具体迭代器(Concrete Iterator):实现迭代器接口,负责管理当前遍历的位置。
- 聚合接口(Aggregate Interface) :定义了创建迭代器的方法,如
createIterator()
。 - 具体聚合类(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 的集合框架(如 ArrayList
、LinkedList
、HashSet
等)广泛使用了迭代器模式。每个集合类都实现了 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() {
// 删除上一次返回的元素
// ...
}
}
三、总结
迭代器模式的优点
- 解耦遍历逻辑与聚合对象 :
- 将遍历逻辑从聚合对象中分离出来,聚合对象可以专注于数据存储,而迭代器负责遍历。
- 符合单一职责原则。
- 统一遍历接口 :
- 提供了一种统一的方式来遍历不同类型的聚合对象(如数组、链表、树等)。
- 客户端代码无需关心聚合对象的内部结构。
- 支持多种遍历方式 :
- 可以为同一个聚合对象定义多个迭代器,实现不同的遍历方式(如正序遍历、逆序遍历、深度优先遍历等)。
- 增强封装性 :
- 隐藏了聚合对象的内部结构,客户端代码只能通过迭代器访问元素,无法直接操作聚合对象的内部数据。
- 开闭原则 :
- 新增聚合类和迭代器类不会影响现有代码,易于扩展。
迭代器模式的缺点
- 增加复杂性 :
- 对于简单的聚合对象,使用迭代器模式可能会增加代码复杂性。
- 如果遍历逻辑非常简单,直接使用 for 循环可能更直观。
- 性能开销 :
- 迭代器模式可能会引入额外的性能开销,尤其是在遍历大型数据集时。
- 不适合频繁修改的聚合对象 :
- 如果聚合对象在遍历过程中频繁修改(如添加或删除元素),可能会导致迭代器失效或抛出异常。
迭代器模式的典型应用场景
- 集合框架 :
- Java 的集合框架(如 ArrayList、LinkedList、HashSet 等)广泛使用了迭代器模式。
- 文件系统遍历 :
- 遍历文件系统中的目录和文件时,可以使用迭代器模式封装遍历逻辑。
- 数据库查询结果遍历 :
- 遍历数据库查询结果集时,可以使用迭代器模式提供统一的遍历接口。
- 树形结构遍历 :
- 遍历树形结构(如 DOM 树、组织结构树等)时,可以使用迭代器模式支持多种遍历方式(如深度优先遍历、广度优先遍历等)。