设计模式精讲 Day 16:迭代器模式(Iterator Pattern)

发布于:2025-06-29 ⋅ 阅读:(15) ⋅ 点赞:(0)

【设计模式精讲 Day 16】迭代器模式(Iterator Pattern)

文章内容

开篇:Day 16 —— 迭代器模式的核心思想与应用价值

在“设计模式精讲”系列的第16天,我们聚焦于迭代器模式(Iterator Pattern)。这是一种行为型设计模式,旨在为集合对象提供一种统一的遍历方式,而无需暴露其内部表示。它通过将遍历逻辑从集合类中解耦,提高了系统的灵活性和可扩展性。

迭代器模式非常适合用于需要对集合进行遍历但又不想让外部直接访问其内部结构的场景。例如,在Java标准库中,Iterator接口就是这一模式的经典实现。掌握该模式不仅有助于理解Java集合框架的设计思想,还能帮助我们在实际项目中更好地管理复杂的数据结构。


模式定义

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

核心思想是:将集合的遍历逻辑封装到一个独立的迭代器对象中,使得客户端代码可以统一地处理不同的集合类型,而无需关心其具体实现。


模式结构

迭代器模式包含以下四个关键角色:

角色 职责
Iterator(迭代器) 定义访问和遍历元素的接口,通常包括 hasNext()next() 方法。
ConcreteIterator(具体迭代器) 实现迭代器接口,负责跟踪当前遍历的位置,并按需返回元素。
Aggregate(聚合对象) 定义创建迭代器对象的接口,通常是一个抽象类或接口。
ConcreteAggregate(具体聚合对象) 实现 createIterator() 方法,返回一个具体的迭代器实例。

适用场景

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

  • 需要统一遍历多种数据结构(如列表、树、图等)。
  • 不希望暴露集合的内部结构,以提高封装性。
  • 需要支持多种遍历方式(如正向、反向、深度优先等)。
  • 需要为集合添加新的遍历算法而不修改现有代码。

实现方式

下面是一个完整的Java实现示例,展示了如何使用迭代器模式遍历一个简单的自定义集合。

// 1. 定义迭代器接口
interface Iterator {
    boolean hasNext();
    Object next();
}

// 2. 定义聚合对象接口
interface Aggregate {
    Iterator createIterator();
}

// 3. 具体聚合对象(如一个数组)
class ConcreteAggregate implements Aggregate {
    private String[] items;

    public ConcreteAggregate(String[] items) {
        this.items = items;
    }

    @Override
    public Iterator createIterator() {
        return new ConcreteIterator(this);
    }
}

// 4. 具体迭代器
class ConcreteIterator implements Iterator {
    private ConcreteAggregate aggregate;
    private int index;

    public ConcreteIterator(ConcreteAggregate aggregate) {
        this.aggregate = aggregate;
        this.index = 0;
    }

    @Override
    public boolean hasNext() {
        return index < aggregate.items.length;
    }

    @Override
    public Object next() {
        if (hasNext()) {
            return aggregate.items[index++];
        } else {
            throw new IndexOutOfBoundsException("No more elements");
        }
    }
}

// 5. 使用示例
public class IteratorPatternDemo {
    public static void main(String[] args) {
        String[] data = {"Apple", "Banana", "Cherry"};
        Aggregate aggregate = new ConcreteAggregate(data);

        Iterator iterator = aggregate.createIterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

代码说明

  • Iterator 接口定义了 hasNext()next() 方法,用于控制遍历过程。
  • ConcreteAggregate 是一个具体的聚合对象,它持有一个字符串数组,并提供了 createIterator() 方法返回一个迭代器。
  • ConcreteIterator 实现了 Iterator 接口,负责遍历数组中的元素。
  • main 方法中,我们创建了一个聚合对象并获取其迭代器,然后依次打印出每个元素。

工作原理

迭代器模式通过将集合的遍历逻辑封装到迭代器对象中,实现了以下几点:

  1. 解耦集合与遍历逻辑:客户端不需要知道集合的具体实现,只需通过迭代器进行操作。
  2. 统一遍历接口:无论集合的结构如何变化,只要提供一个迭代器,就能进行统一的遍历。
  3. 支持多种遍历方式:可以通过扩展迭代器来实现不同的遍历策略,如正向、反向、过滤等。

优缺点分析

优点 缺点
提高了系统的封装性和灵活性 增加了系统复杂度
支持多种遍历方式 可能导致性能开销
降低客户端与集合之间的耦合 需要额外编写迭代器类

案例分析:电商商品列表的分页展示

问题描述

在一个电商平台中,我们需要展示商品列表,并且支持分页功能。由于商品数量可能非常大,不能一次性加载所有数据,因此需要实现分页查询。

解决方案

我们可以使用迭代器模式来实现分页功能,其中每一页的数据作为一个“迭代单元”,通过迭代器逐个获取。

// 分页迭代器接口
interface PageIterator {
    boolean hasNextPage();
    List<String> nextPage();
}

// 分页聚合对象
interface PageableAggregate {
    PageIterator createPageIterator();
}

// 具体聚合对象(模拟数据库查询)
class ProductAggregate implements PageableAggregate {
    private List<String> products;
    private int pageSize;

    public ProductAggregate(List<String> products, int pageSize) {
        this.products = products;
        this.pageSize = pageSize;
    }

    @Override
    public PageIterator createPageIterator() {
        return new ProductPageIterator(this);
    }
}

// 具体分页迭代器
class ProductPageIterator implements PageIterator {
    private ProductAggregate aggregate;
    private int currentPage = 0;

    public ProductPageIterator(ProductAggregate aggregate) {
        this.aggregate = aggregate;
    }

    @Override
    public boolean hasNextPage() {
        return currentPage * aggregate.pageSize < aggregate.products.size();
    }

    @Override
    public List<String> nextPage() {
        int start = currentPage * aggregate.pageSize;
        int end = Math.min(start + aggregate.pageSize, aggregate.products.size());

        List<String> page = aggregate.products.subList(start, end);
        currentPage++;
        return page;
    }
}

// 使用示例
public class PageIteratorDemo {
    public static void main(String[] args) {
        List<String> allProducts = Arrays.asList(
                "Product A", "Product B", "Product C",
                "Product D", "Product E", "Product F"
        );

        PageableAggregate aggregate = new ProductAggregate(allProducts, 2);

        PageIterator iterator = aggregate.createPageIterator();

        while (iterator.hasNextPage()) {
            List<String> page = iterator.nextPage();
            System.out.println("Page: " + page);
        }
    }
}

效果

此实现允许我们按页加载商品列表,避免一次性加载过多数据,提升系统性能。同时,客户端代码无需关心分页逻辑的实现细节,只需要调用 hasNextPage()nextPage() 即可。


与其他模式的关系

迭代器模式常与其他设计模式结合使用,例如:

  • 组合模式(Composite Pattern):在遍历树形结构时,迭代器可以递归地访问子节点。
  • 访问者模式(Visitor Pattern):可以在迭代过程中对元素执行特定的操作。
  • 命令模式(Command Pattern):可以将遍历请求封装为命令对象,实现更灵活的控制。

此外,迭代器模式与工厂模式也有一定的关联,因为工厂可以用来创建不同类型的迭代器。


总结

本节我们深入讲解了迭代器模式,包括它的定义、结构、适用场景、实现方式、工作原理、优缺点以及实际案例。通过学习该模式,我们可以更好地理解如何在不暴露集合内部结构的前提下,实现统一的遍历逻辑。

迭代器模式在Java标准库中广泛应用,例如 Iterator 接口和 Iterable 接口。掌握该模式有助于我们在实际项目中设计更灵活、可维护的集合遍历逻辑。


下一节预告

在接下来的 Day 17 中,我们将介绍 中介者模式(Mediator Pattern),它用于简化多个对象之间的通信,特别适合用于 GUI 系统或复杂的交互场景。


文章标签

design-patterns, iterator-pattern, java, software-design, object-oriented-programming, code-examples, java-coding, software-architecture, design-patterns-in-java


文章简述

本文详细介绍了设计模式中的迭代器模式(Iterator Pattern),涵盖其核心思想、实现方式、适用场景及实际应用案例。通过完整的 Java 代码示例,读者可以直观地理解如何利用该模式实现对集合的统一遍历。文章还对比了该模式与其他设计模式的关系,并分析了其优缺点。对于希望提升代码结构和可维护性的 Java 开发者来说,本文提供了实用的技术指导和最佳实践。


网站公告

今日签到

点亮在社区的每一天
去签到