当前位置: 首页 > news >正文

行为模式-迭代器模式

定义:

        Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.(它提供一种方法访问一个容器对象中各个元素,而又不需暴露该 对象的内部细节。)

迭代器模式通用类图

        迭代器设计模式的核心是将集合对象的遍历行为抽象出来,封装到一个独立的迭代器对象中。这样,集合对象就不需要自己实现遍历逻辑,而是将遍历的责任委托给迭代器对象。客户端只需要通过迭代器提供的接口来访问集合元素,而不需要了解集合的内部结构。这种设计方式不仅使集合的接口和实现更加简洁,还可以支持多种不同的遍历方式,提高了代码的可维护性和可扩展性。

角色:

迭代器模式包含以下几个核心角色:

1、迭代器接口(Iterator)

        迭代器接口定义了访问和遍历元素的方法,如`hasNext()`(判断是否还有下一个元素)、`next()`(返回下一个元素)等。所有具体迭代器都必须实现这个接口,确保客户端可以以统一的方式使用迭代器。

2、具体迭代器(Concrete Iterator)

        具体迭代器实现了迭代器接口,负责跟踪集合中元素的当前位置,并实现各种遍历方法。具体迭代器通常会持有一个对具体集合对象的引用,以便访问集合中的元素。

3、集合接口(Aggregate)

        集合接口定义了创建迭代器对象的方法,如`createIterator()`。所有具体集合都必须实现这个接口,以便客户端可以请求创建适合该集合的迭代器。

4、具体集合(Concrete Aggregate)

        具体集合实现了集合接口,负责创建相应的具体迭代器对象。具体集合通常包含一个存储元素的数据结构,如数组、列表等。

代码示例:

        下面通过一个简单的示例来展示迭代器设计模式的实现。假设我们有一个自定义的书架类,需要实现对书架上书籍的遍历功能。

// 书籍类

public class Book {private String name;private String author;public Book(String name, String author) {this.name = name;this.author = author;}public String getName() {return name;}public String getAuthor() {return author;}@Overridepublic String toString() {return "《" + name + "》 - " + author;}}

// 迭代器接口

public interface Iterator<T> {boolean hasNext();T next();}

// 具体迭代器:书架迭代器

public class BookShelfIterator implements Iterator<Book> {private BookShelf bookShelf;private int index;public BookShelfIterator(BookShelf bookShelf) {this.bookShelf = bookShelf;this.index = 0;}@Overridepublic boolean hasNext() {return index < bookShelf.getLength();}@Overridepublic Book next() {Book book = bookShelf.getBookAt(index);index++;return book;}}

// 集合接口

public interface Aggregate<T> {Iterator<T> createIterator();}

// 具体集合:书架

public class BookShelf implements Aggregate<Book> {private Book[] books;private int last = 0;public BookShelf(int maxSize) {this.books = new Book[maxSize];}public Book getBookAt(int index) {return books[index];}public void appendBook(Book book) {this.books[last] = book;last++;}public int getLength() {return last;}@Overridepublic Iterator<Book> createIterator() {return new BookShelfIterator(this);}}

// 客户端代码

public class IteratorPatternClient {public static void main(String[] args) {// 创建书架并添加书籍BookShelf bookShelf = new BookShelf(4);bookShelf.appendBook(new Book("Java编程思想", "Bruce Eckel"));bookShelf.appendBook(new Book("设计模式", "Erich Gamma"));bookShelf.appendBook(new Book("算法导论", "Thomas H. Cormen"));bookShelf.appendBook(new Book("计算机程序的构造和解释", "Harold Abelson"));// 使用迭代器遍历书架上的书籍Iterator<Book> iterator = bookShelf.createIterator();System.out.println("书架上的书籍:");while (iterator.hasNext()) {Book book = iterator.next();System.out.println(book);}}}

优点 :

1、支持多种遍历方式:迭代器模式可以为一个聚合对象提供多种不同的遍历方式,客户端可以根据需要选择合适的迭代器,而不需要修改聚合对象的代码。

2、简化聚合对象的接口:迭代器模式将遍历逻辑从聚合对象中分离出来,使得聚合对象的接口更加简洁,只需要关注元素的存储和管理,而不需要关注遍历逻辑。

3、符合单一职责原则:迭代器模式将遍历逻辑封装在迭代器类中,使得聚合对象和迭代器类各自承担自己的职责,符合单一职责原则。

4、符合开闭原则:迭代器模式可以在不修改聚合对象代码的情况下,通过增加新的迭代器类来支持新的遍历方式,符合开闭原则。

5、隐藏聚合对象的内部结构:迭代器模式可以将聚合对象的内部结构隐藏起来,客户端只需要通过迭代器提供的接口访问元素,提高了系统的安全性。


缺点:

1、增加类的数量:迭代器模式需要定义迭代器接口、具体迭代器类、聚合接口和具体聚合类等多个类,会增加系统的类数量,使代码结构变得复杂。

2、对于简单的聚合结构可能过于繁琐:对于简单的聚合结构,如数组,直接使用循环遍历可能更加简单和高效,使用迭代器模式可能会显得过于繁琐。

3、迭代器的维护成本:当聚合对象的内部结构发生变化时,可能需要修改迭代器的实现,增加了维护成本。


使用场景: 

(一)需要为聚合对象提供多种遍历方式

        当一个聚合对象需要支持多种不同的遍历方式时,如正向遍历、反向遍历、跳跃遍历等,可以使用迭代器模式将不同的遍历逻辑封装到不同的迭代器类中,客户端可以根据需要选择合适的迭代器。

(二)需要隐藏聚合对象的内部结构

        迭代器模式可以将聚合对象的内部结构隐藏起来,客户端只需要通过迭代器提供的接口访问元素,而不需要了解聚合对象的具体实现。这样可以保护聚合对象的内部数据不被非法访问。

(三)需要为不同的聚合结构提供统一的遍历接口

        当系统中存在多种不同类型的聚合结构(如数组、列表、树等),且需要为它们提供统一的遍历接口时,迭代器模式可以定义一个统一的迭代器接口,不同的聚合结构实现各自的具体迭代器,使得客户端可以使用相同的代码遍历不同的聚合结构。

(四)需要在遍历的同时对元素进行特定操作

        在遍历聚合对象的过程中,可能需要对元素进行特定的操作,如过滤、转换等。迭代器模式可以在迭代器中实现这些操作,使得遍历和操作可以同时进行,提高代码的灵活性。

        迭代器设计模式通过将集合对象的遍历行为抽象出来,封装到独立的迭代器对象中,为我们提供了一种统一且灵活的方式来访问集合元素。它在不暴露集合内部结构的情况下,支持多种遍历方式,简化了集合接口,提高了代码的可维护性和可扩展性。在实际开发中,当我们需要处理集合的遍历问题,特别是需要支持多种遍历方式或隐藏集合内部结构时,迭代器模式是一个不错的选择。但也要注意避免在简单场景中过度使用,以免增加系统的复杂性。掌握迭代器设计模式,能够让我们的代码更加简洁、灵活和易于维护。

相关文章:

  • 基于sample_aiisp再创建一路 h264编码流,和jpg的编码流
  • vue中的三种插槽方式
  • ABP vNext + OpenIddict:自定义 OAuth2/OpenID Connect 认证策略
  • 如何从 Windows 11 或 10 远程访问 Ubuntu 24.04 或 22.04 桌面
  • 使用 C++ 和 OpenCV 构建智能停车场视觉管理系统
  • Linux NFS服务器配置
  • JavaScript数组方法总结
  • 每日Prompt:Steve Winter风格插画
  • PyTorch框架-自动微分模块
  • 将MySQL数据库中所有表和字段编码统一改为utf8mb4_unicode_ci
  • 影像组学5:Radiomics Score的计算
  • 系统常用线程池配置,使用与注意事项
  • 【Android】EventBus详解
  • 【测试开发】面向对象-魔术方法
  • 企业架构框架深入解析:TOGAF、Zachman Framework、FEAF与Gartner EA Framework
  • python打卡day53@浙大疏锦行
  • HarmonyOS 组件复用面试宝典 [特殊字符]
  • 《AI日报 · 0613|ChatGPT支持导出、Manus免费开放、GCP全球宕机》
  • 每天宜搭宜搭小知识—报表组件—柱线混合图
  • 【实用生信代码】分子对接后的分子动力学模拟实战——OpennMM
  • 网站建设价格差别/aso优化公司
  • 郑州网站优化公司排名/沈阳企业网站seo公司
  • 做网站绍兴/站长工具果冻传媒
  • 石林彝族网站建设/公司网站建设代理
  • 门户网站快速制作/凡科建站官网入口
  • 从零开始学做网站cdsn/免费创建网站