当前位置: 首页 > 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、迭代器的维护成本:当聚合对象的内部结构发生变化时,可能需要修改迭代器的实现,增加了维护成本。


使用场景: 

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

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

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

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

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

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

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

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

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

http://www.xdnf.cn/news/1021717.html

相关文章:

  • JVM常见面试题
  • redis-7.4.4使用
  • 详解deeplabv3+改进思路
  • conda pack迁出环境异常
  • AKS升级路线最佳实践方案
  • dockercompose部署应用
  • 实战案例-JESD204B 多器件同步
  • 协同开发中的移动端网页调试流程:一次团队实战的经验总结(含WebDebugX)
  • Unity 接入抖音小游戏一
  • linux 黑马 第1-2章
  • ELK日志采集系统
  • 通过iframe使用Jupyter notebook
  • shell、bash、cmd、git 和 PowerShell 的区别与关系的详细解析
  • 吃透 Golang 基础:函数
  • 混合云战略规划深度解析:多云管理的技术架构与治理框架
  • 动态规划: 背包DP大合集
  • 【android bluetooth 框架分析 04】【bt-framework 层详解 7】【AdapterProperties介绍】
  • 触觉智能RK3576核心板,工业应用之4K超高清HDMI IN视频输入
  • 基于Python的二手房源信息爬取与分析的设计和实现,7000字论文编写
  • 改写爬虫, unsplash 图片爬虫 (网站改动了,重写爬虫)
  • 给element-plus的table表格加上连续序号
  • Kubernetes 从入门到精通-资源限制
  • 清理电脑C磁盘,方法N:使用【360软件】中的【清理C盘空间】
  • Visual Studio Code 1.101.0 官方版
  • 晶晨S905L/S905L-B芯片-安卓7.1.2_【通刷】线刷固件包及教程
  • 解析Android SETUP_DATA_CALL 链路信息字段
  • MultiTalk 是一种音频驱动的多人对话视频生成模型
  • Java 实现 Excel 转化为图片
  • 亚远景-如何高效实施ASPICE认证标准:汽车软件企业的实践指南
  • nvue全攻略:从入门到性能优化