Java二十三种设计模式-迭代子模式(16/23)

news2024/9/21 15:31:53

迭代器模式:顺序访问集合的稳健方式

引言

迭代器模式(Iterator Pattern)是一种行为型设计模式,它允许顺序访问一个集合对象中的各个元素,而不需要暴露集合的底层表示。

 基础知识,java设计模式总体来说设计模式分为三大类:

(1)创建型模式,共5种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

(2)结构型模式,共7种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

(3)行为型模式,共11种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

第一部分:迭代器模式概述

1.1 定义与用途

迭代器模式的基本定义

迭代器模式是一种行为型设计模式,用于提供一种顺序访问集合元素的方法,而不暴露集合的内部结构。迭代器模式定义了一种迭代访问一个聚合对象中各个元素的接口,允许在不暴露其内部表示的情况下,顺序访问聚合对象中的各个元素。

解释为何需要迭代器模式

  • 抽象化遍历过程:迭代器模式将遍历机制从集合类中抽象出来,使得遍历过程与集合的具体实现无关。
  • 支持多种遍历方式:不同的迭代器可以实现不同的遍历方式,如正向遍历、反向遍历等。
  • 解耦集合与遍历:迭代器模式将集合与其遍历方式解耦,使得可以在不修改集合类的情况下,引入新的遍历方式。
  • 简化客户端代码:客户端代码通过统一的接口与集合交互,无需关心集合的具体实现细节。

1.2 迭代器模式的组成

迭代器(Iterator)

  • 定义:迭代器定义了访问和遍历集合元素的接口,通常包含hasNext()next()remove()等方法。
  • 职责:提供遍历集合的机制,允许访问集合中的每个元素。

集合(Aggregate)

  • 定义:集合负责创建迭代器对象,并对迭代器进行管理。
  • 职责:定义一个方法,用于返回一个迭代器对象,允许访问其元素。

具体迭代器(Concrete Iterator)

  • 定义:具体迭代器实现了迭代器接口,提供了遍历集合的具体实现。
  • 职责:跟踪当前遍历的位置,并实现迭代器接口的方法。

具体集合(Concrete Aggregate)

  • 定义:具体集合实现了集合接口,管理其内部的元素存储。
  • 职责:存储集合的元素,并提供一个方法返回一个具体迭代器的实例。

角色之间的交互

  • 创建迭代器:客户端通过集合的createIterator()方法获取迭代器对象。
  • 遍历集合:客户端使用迭代器的hasNext()next()方法遍历集合中的元素。
  • 维护状态:具体迭代器在遍历过程中维护当前遍历的位置。

迭代器模式通过提供一种统一的访问接口,允许客户端顺序访问集合中的元素,同时隐藏了集合的内部结构。这种模式在需要对集合进行多种方式遍历或需要隐藏集合内部实现的情况下非常有用。在下一部分中,我们将通过Java代码示例来展示迭代器模式的具体实现。

第二部分:迭代器模式的实现

2.1 Java实现示例

以下是使用Java语言实现迭代器模式的代码示例。我们将创建一个简单的书籍集合,并使用迭代器来遍历这些书籍。

// 书籍接口
interface Book {
    String getTitle();
    String getAuthor();
}

// 具体书籍
class ConcreteBook implements Book {
    private String title;
    private String author;

    public ConcreteBook(String title, String author) {
        this.title = title;
        this.author = author;
    }

    @Override
    public String getTitle() {
        return title;
    }

    @Override
    public String getAuthor() {
        return author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "title='" + title + '\'' +
                ", author='" + author + '\'' +
                '}';
    }
}

// 集合接口
interface BookShelf {
    Iterator<Book> createIterator();
}

// 具体集合
class ConcreteBookShelf implements BookShelf {
    private List<Book> books = new ArrayList<>();

    public void addBook(Book book) {
        books.add(book);
    }

    @Override
    public Iterator<Book> createIterator() {
        return new ConcreteIterator<>(books);
    }
}

// 迭代器接口
interface Iterator<T> {
    boolean hasNext();
    T next();
}

// 具体迭代器
class ConcreteIterator<T> implements Iterator<T> {
    private List<T> items;
    private int position = 0;

    public ConcreteIterator(List<T> items) {
        this.items = items;
    }

    @Override
    public boolean hasNext() {
        return position < items.size();
    }

    @Override
    public T next() {
        return items.get(position++);
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        BookShelf bookShelf = new ConcreteBookShelf();
        bookShelf.addBook(new ConcreteBook("Java Design Patterns", "Sven Walter"));
        bookShelf.addBook(new ConcreteBook("Clean Code", "Robert C. Martin"));

        Iterator<Book> iterator = bookShelf.createIterator();
        while (iterator.hasNext()) {
            Book book = iterator.next();
            System.out.println(book);
        }
    }
}

2.2 迭代器模式中的角色和职责

迭代器(Iterator)

  • 职责:定义了访问集合元素的接口,提供了遍历集合的方法。

集合(Aggregate)

  • 职责:负责创建迭代器对象,允许外部代码通过迭代器访问集合中的元素。

具体迭代器(Concrete Iterator)

  • 职责:实现了迭代器接口,维护遍历状态,包括当前遍历到的位置。

具体集合(Concrete Aggregate)

  • 职责:实现了集合接口,存储具体的元素,并提供创建迭代器的方法。

相互作用

  • 创建迭代器:客户端通过具体集合的createIterator()方法获取一个迭代器实例。
  • 遍历集合:客户端使用迭代器的hasNext()next()方法来遍历集合中的元素。
  • 维护状态:具体迭代器在遍历过程中维护当前的位置,确保能够正确地访问每个元素一次。

迭代器模式提供了一种强大的方式来访问集合中的元素,同时隐藏了集合的内部实现。这种模式在需要对集合进行多种遍历方式或需要隐藏集合内部实现的情况下非常有用。在下一部分中,我们将探讨迭代器模式的使用场景。

 

第三部分:迭代器模式的使用场景

3.1 需要访问复杂集合的场景

在软件开发中,经常会遇到需要访问复杂集合的情况,这些集合可能包含大量数据,或者具有复杂的内部结构。

讨论在需要访问复杂集合时,迭代器模式的应用:

  • 简化遍历逻辑:迭代器模式提供了一种统一的方法来遍历集合中的元素,无论集合的内部结构如何复杂。
  • 提供定制遍历:通过实现不同的迭代器,可以提供不同的遍历策略,如深度优先、广度优先等。

应用实例:

  • 多维数组:在处理多维数组或矩阵时,迭代器模式可以简化遍历过程,提供一致的访问接口。
  • 树形结构:在树形数据结构中,迭代器可以提供多种遍历方式,如前序、中序、后序遍历。

3.2 需要隐藏集合内部结构的场景

在某些情况下,我们可能不希望外部代码了解集合的具体实现细节,以保护数据的封装性或实现特定的设计需求。

分析在需要隐藏集合内部结构时,迭代器模式的优势:

  • 封装性:迭代器模式隐藏了集合的内部实现,客户端代码通过迭代器与集合交互,不需要了解集合的具体结构。
  • 解耦合:通过隐藏内部结构,迭代器模式降低了客户端代码与集合实现之间的耦合度。

应用实例:

  • 数据访问对象(DAO):在数据访问层,迭代器模式可以用于封装对数据库查询结果的访问,隐藏SQL查询的细节。
  • 图形界面库:在图形界面编程中,迭代器模式可以用于遍历组件树,而不需要暴露组件树的具体实现。

迭代器模式通过提供一个统一的访问接口,使得客户端代码可以方便地访问集合中的元素,同时隐藏了集合的内部结构。这种模式在实际开发中非常有价值,尤其是在需要处理复杂集合或保护集合实现细节的场景中。在下一部分中,我们将讨论迭代器模式的优点与缺点。

第四部分:迭代器模式的优点与缺点

4.1 优点

提供统一的访问接口

  • 一致性: 迭代器模式为不同的集合类型提供了一致的访问方式,简化了客户端代码。

支持多样的遍历方式

  • 灵活性: 通过实现不同的迭代器,可以支持正向、反向、深度优先等多种遍历方式。

隐藏内部结构

  • 封装性: 迭代器模式隐藏了集合的具体实现细节,保护了数据的封装性。

增加系统可扩展性

  • 扩展性: 当需要添加新的遍历方式时,可以通过添加新的迭代器实现,无需修改现有代码。

简化客户端代码

  • 简化访问: 客户端通过简单的迭代器接口与集合交互,无需关心集合的具体类型和实现。

4.2 缺点

增加系统复杂性

  • 理解难度: 对于初学者来说,迭代器模式可能增加了对系统的理解和学习难度。

迭代器实现的复杂性

  • 实现成本: 对于某些集合类型,实现一个高效的迭代器可能需要额外的设计和开发工作。

性能考虑

  • 性能开销: 在某些情况下,使用迭代器模式可能会引入额外的性能开销,尤其是在迭代器的创建和使用过程中。

固定遍历顺序

  • 顺序限制: 某些迭代器可能只提供了固定的遍历顺序,限制了遍历方式的灵活性。

线程安全问题

  • 并发访问: 在多线程环境中,迭代器的线程安全问题需要特别注意和处理。

迭代器模式通过提供一个统一的访问接口和隐藏集合的内部结构,为集合的遍历提供了极大的灵活性和便利。然而,它也可能带来一些缺点,如系统复杂性的增加和性能开销。在实际应用中,开发者需要根据具体需求和场景权衡是否使用迭代器模式,并注意避免其潜在的缺点。在下一部分中,我们将比较迭代器模式与其他设计模式,并提供一些最佳实践和建议。

第五部分:迭代器模式与其他模式的比较

5.1 与组合模式的比较

组合模式(Composite Pattern)

  • 定义:组合模式是一种结构型设计模式,用于将对象组合成树形结构,以表示“部分-整体”的层次结构。
  • 特点:它允许用户以一致的方式处理个别对象和组合对象。

迭代器模式

  • 定义:迭代器模式提供了一种顺序访问集合元素的方式,而不暴露集合的内部结构。

对比

  • 树形结构:组合模式特别适用于树形结构,允许用户通过一致的接口处理树中的所有元素。
  • 遍历方式:迭代器模式更关注于集合的遍历方式,不关心集合是否形成树形结构。

5.2 与访问者模式的对比

访问者模式(Visitor Pattern)

  • 定义:访问者模式是一种行为型设计模式,用于对对象结构中的元素执行操作,而不需要修改对象结构本身。
  • 特点:它将算法从对象结构中分离出来,通过访问者对象对元素进行操作。

迭代器模式

  • 定义:如前所述,迭代器模式用于顺序访问集合中的元素。

对比

  • 行为扩展:访问者模式允许在不修改对象结构的情况下添加新的操作,而迭代器模式专注于提供遍历集合的方法。
  • 关注点:访问者模式关注于元素的操作,迭代器模式关注于元素的访问和遍历。

迭代器模式提供了一种简单而强大的方式来遍历集合中的元素,而组合模式和访问者模式则提供了处理更复杂对象结构的方法。每种模式都有其独特的用途和优势,选择使用哪种模式取决于具体的设计需求和场景。在下一部分中,我们将提供迭代器模式的最佳实践和建议。

第六部分:迭代器模式的最佳实践和建议

6.1 最佳实践

确保迭代器的线程安全

  • 线程安全:确保迭代器在多线程环境中使用时是安全的,避免并发修改异常。

避免在迭代器中修改集合

  • 不变性:迭代器遍历过程中应保持集合不变,如需修改,应在迭代结束后进行。

提供丰富的迭代器实现

  • 多样性:根据需要实现多种类型的迭代器,例如ListIterator提供双向遍历和修改能力。

遵循Java迭代器规范

  • 规范性:在Java中实现迭代器时,遵循Java Collections Framework的规范和约定。

实现可撤销的迭代器

  • 可撤销操作:如果可能,实现支持撤销操作的迭代器,以支持复杂的交互式应用。

考虑使用泛型

  • 类型安全:使用泛型来保证迭代器操作的类型安全。

6.2 避免滥用

避免过度使用迭代器模式

  • 适用性:仅在需要对集合进行复杂遍历或需要隐藏遍历逻辑时使用迭代器模式。

避免在简单集合上使用迭代器

  • 简化设计:对于简单的集合操作,直接使用原生的for循环或Java的增强for循环可能更简单明了。

避免复杂的迭代器实现

  • 简化实现:尽量保持迭代器的实现简单,避免引入不必要的复杂性。

6.3 替代方案

使用for-each循环

  • 简化遍历:对于大多数遍历需求,Java的for-each循环提供了一种更简洁的遍历方式。

使用Java Streams

  • 函数式编程:利用Java Streams API进行集合操作,支持函数式编程风格。

使用数据库游标

  • 数据库遍历:在处理数据库查询结果时,使用数据库游标进行遍历。

使用观察者模式

  • 事件驱动:在某些情况下,使用观察者模式来响应集合的变化可能更合适。

迭代器模式是一种强大的设计模式,用于提供统一的集合元素访问方式,同时隐藏集合的具体实现。然而,合理使用迭代器模式并避免其缺点是至关重要的。了解其替代方案可以帮助开发者根据具体需求和场景选择最合适的设计模式。在实际开发中,应根据具体情况灵活运用迭代器模式,以达到最佳的设计效果。

结语

迭代器模式提供了一种强大的方式来顺序访问集合中的元素,同时隐藏了集合的具体实现。通过本文的深入分析,希望读者能够对迭代器模式有更全面的理解,并在实际开发中做出合理的设计选择。

博主还写了其他Java设计模式关联文章,请各位大佬批评指正:

(一)创建型模式(5种):

Java二十三种设计模式-单例模式(1/23)

Java二十三种设计模式-工厂方法模式(2/23)

Java二十三种设计模式-抽象工厂模式(3/23)

Java二十三种设计模式-建造者模式(4/23)

Java二十三种设计模式-原型模式(5/23)

(二)结构型模式(7种): 

Java二十三种设计模式-适配器模式(6/23)

Java二十三种设计模式-装饰器模式(7/23)

Java二十三种设计模式-代理模式(8/23)

Java二十三种设计模式-外观模式(9/23)

Java二十三种设计模式-桥接模式(10/23)

Java二十三种设计模式-组合模式(11/23)

Java二十三种设计模式-享元模式(12/23)

 (三)行为型模式(11种): 

Java二十三种设计模式-策略模式(13/23)

Java二十三种设计模式-模板方法模式(14/23)

Java二十三种设计模式-观察者模式(15/23)

持续更新中...... 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2048836.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP32-C3在MQTT访问时出现“transport_base: Poll timeout or error”问题的分析(1)

笔者最近在测试时,突然遇到了以下错误: 网上看过一些帖子,要么就是只提出遇到了相同问题,但没有解答。如:transport_base: Poll timeout or error, errno=Connection already in progress - ESP32 Forum 要么就是和本问题类似,但不完全相同的问题。如: TRANSPORT_BASE:…

Tomcat学习进阶

目录 Apache Tomcat架构配置线程模型Tomcat 的类加载机制类加载器层次结构类加载流程 Tomcat 的优化策略Tomcat 的集群部署Tomcat故障排查 Apache Tomcat 架构配置 Apache Tomcat是一个开源的Java Servlet容器和Web服务器&#xff0c;它实现了Java EE规范中的Servlet和JSP API。…

mysql中的innodb存储结构

什么是InnoDB存储引擎 InnoDB是MySQL的默认存储引擎&#xff0c;它是一个事务安全的存储引擎&#xff0c;支持行级锁定和外键约束。InnoDB为MySQL提供了高性能、高可靠性和高可用性的解决方案。 InnoDB 的核心特点和功能 事务支持&#xff1a;InnoDB支持ACID事务特性&#x…

[算法题]【模板】前缀和/【模板】二维前缀和

题目链接: 【模板】前缀和 / 【模板】二维前缀和 两道前缀和模板题. 【模板】前缀和: 定义一维前缀和数组: presum[i]: 表示 1 - i 位置的和 状态转移方程: presum[i] presum[i - 1] arr[i - 1] 定义数组时多开一个位置, 下标位置从 1 开始计算, 不从 0 开始是为了避免越界…

我眼中的胶水工作:挑战与机遇并存

我眼中的胶水工作&#xff1a;挑战与机遇并存 胶水工作&#xff0c;看似不起眼&#xff0c;却如同团队运作的隐形脉络&#xff0c;起着至关重要的连接作用。它涵盖了各种各样的任务&#xff0c;从注意到团队成员的阻碍并伸出援手&#xff0c;到审查设计文档&#xff0c;再到新…

实现微信的订阅消息或模板消息API来实现实时通知(服务通知)

实现微信的订阅消息或模板消息API以实现实时通知&#xff0c;需要经过几个关键步骤&#xff0c;包括用户订阅、消息发送和接收消息事件。以下是具体实现流程&#xff1a; 1. 用户订阅消息 首先&#xff0c;需要让用户订阅消息。这通常通过前端代码触发一个授权请求来完成&am…

C:每日一题:字符串左旋

题目&#xff1a;实现一个函数&#xff0c;可以实现字符串的左旋 例如&#xff1a;ABCD左旋一个字符就是BCDA&#xff1b;ABCD左旋两个字符就是CDAB&#xff1b; 1、解题思路&#xff1a; 1.确定目标旋转k个字符&#xff0c;我们要获取字符串的长度 len&#xff0c;目的是根…

8.14 day bug

bug1 好家伙&#xff0c;折腾一个小时没通过&#xff0c;原来是代码写多了 // 定义初始状态 const defaultState {login: false };// 定义 reducer const reducer (state defaultState, action) > {if (action.typeLOGIN) {// 当接收到 LOGIN action 时&#xff0c;更新…

备战秋招60天算法挑战,Day20

题目链接&#xff1a; https://leetcode.cn/problems/reverse-bits/ 视频题解&#xff1a; https://www.bilibili.com/video/BV1W2421Z7bi/ LeetCode 190.颠倒二进制位 题目描述 颠倒给定的 32 位无符号整数的二进制位。 举个例子&#xff1a; 输入&#xff1a;n 00000010…

Nginx--简介、安装、常用命令和配置文件

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、Nginx简介 1、nginx介绍 Nginx (engine x) 是一个高性能的 HTTP 和 反向代理 服务&#xff0c;也是一个IMAP/POP3/SMTP服务。因它的稳定性、丰…

分布式锁实现方案--redis、zookeeper、mysql

分布式锁的几种实现方式 悲观锁和乐观锁分布式锁的实现要求 -- 互斥性、避免死锁、可重入性、高可用行、性能互斥-只能有一个客户端持有锁 -- redis setnx避免死锁引入过期时间 -- redis ttl锁过期问题 -- 自动续期 -- redis释放别人锁问题 -- 锁附加唯一性 -- 给每个客户端设置…

【嵌入式linux开发】智能家居入门6:最新ONENET,物联网开放平台(QT、微信小程序、MQTT协议、ONENET云平台、旭日x3派)

智能家居入门6&#xff1a;最新ONENET物联网开放平台 前言最终现象一、ONENET云平台创建产品与设备二、使用MQTT客户端软件测试2.1 测试前的准备2.2 测试 三、LInux QT代码四、onenet 云端API介绍及微信小程序代码4.1 onenet API介绍4.2 微信小程序代码 五、板端运行 前言 ONE…

LeetCode 热题100-24

回文链表 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,2,1] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff…

四层负载企业实战

通过四层负载LVSkeepalived将请求转发到nginx代理服务器。通过代理服务器访问后端真实应用服务。 拓补图&#xff1a; 准备环境6台机器&#xff1b; lvskeepalived---两台 nginx代理 ---两台 tomcat----一台 php ----一台 所有机器关闭防火墙和selinux 所有机器解析如下…

APP安全检测报告内容详解

一、APP安全检测的必要性 APP安全检测是确保移动应用安全的重要一环。在开发过程中&#xff0c;由于技术、人员和管理等方面的原因&#xff0c;APP可能存在各种安全漏洞和风险。这些漏洞一旦被黑客利用&#xff0c;可能导致用户数据泄露、恶意代码注入、应用被篡改等严重后果。…

Windows下使用QT5.14.2编译MySQL8.0对应的最新64位驱动程序步骤

不得不说mysql更新的速度是真的快&#xff0c;最近一两年都更新了好几个的小版本了。如果安装了高版本的 mysql软件&#xff0c;低版本的驱动就不支持了&#xff0c;因此需要重新使用QT来编译对应的mysql驱动。具体办法如下&#xff1a; 1、官网下载最新的mysql8.0安装包。下载…

day04--js的综合案例

1.1 商品全选 需求&#xff1a;商品全选 1. 全选 &#xff1a;点击全选按钮,所有复选框都被选中 2. 全不选 &#xff1a;点击全不选按钮,所有复选框都被取消选中 3. 反选 &#xff1a; 点击反选按钮,所有复选框状态取反 <!DOCTYPE html> <html lang"en">…

智慧校园云平台电子班牌系统源码,智慧教育一体化云解决方案

智慧校园云平台电子班牌系统&#xff0c;利用先进的云计算技术&#xff0c;将教育信息化资源和教学管理系统进行有效整合&#xff0c;实现生态基础数据共享、应用生态统一管理&#xff0c;为智慧教育建设的统一性&#xff0c;稳定性&#xff0c;可扩展性&#xff0c;互通性提供…

利用PDAL库实现Las文件向PLY文件的转换

1、官网的下载链接 PDAL&#xff08;Point Data Abstraction Library&#xff09;是一个开源的C库&#xff0c;专门用于处理三维点云数据。它提供了数据读取、转换、过滤、统计分析等多种功能&#xff0c;支持多种数据格式&#xff0c;如LAS、LiDAR、ASCII等。在IT行业中&…

Java常用集合(List、Map)类型相关问题整理

一、背景 针对Java基础集合的部分&#xff0c;对一些常见的问题进行整理&#xff0c;方便后续能够随时复习 二、问题与回答 &#xff08;1&#xff09;Java集合类ArrayList初始化时数组的默认长度是多少&#xff1f; 答&#xff1a;在new ArrayList() 这段代码执行完后&a…