设计模式第16讲——迭代器模式(Iterator)

news2024/11/15 14:10:57

目录

一、什么是迭代器模式

二、角色组成

三、 优缺点

四、应用场景

4.1 生活场景

4.2 java场景

五、代码实现 

5.0 代码结构

5.1 Student——学生实体类

5.2 StudentIterator——抽象迭代器(Iterator)

5.3 StudentListIterator——具体迭代器(Concrete iterator)

5.4 StudentAggregate——抽象聚合器(Aggregate)

5.5 ClassList——具体聚合器(Concrete Aggregate)

5.6 testIterator

六、总结


一、什么是迭代器模式

迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。

二、角色组成

  • 抽象迭代器(Iterator):定义了遍历聚合对象所需的方法,包括hashNext()next()方法等,用于遍历聚合对象中的元素。
  • 具体迭代器(Concrete Iterator):它是实现迭代器接口的具体实现类,负责具体的遍历逻辑。它保存了当前遍历的位置信息,并可以根据需要向前或向后遍历集合元素。
  • 抽象容器(Aggregate): 一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
  • 具体容器角色(ConcreteAggregate):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。

三、 优缺点

优点:

  • 简化了集合类的接口,使用者可以更加简单地遍历集合对象,而不需要了解集合内部结构和实现细节。
  • 将集合和遍历操作解耦,使得我们可以更灵活地使用不同的迭代器来遍历同一个集合,根据需求选择不同的遍历方式。
  • 满足开闭原则,如果需要增加新的遍历方式,只需实现一个新的具体迭代器即可,不需要修改原先聚合对象的代码。

缺点:

  • 具体迭代器实现的算法对外不可见,因此不利于调试和维护。
  • 对于某些小型、简单的集合对象来说,使用迭代器模式可能会显得过于复杂,增加了代码的复杂性。

四、应用场景

4.1 生活场景

  • 遍历班级名单:假设你是一名班主任,你需要遍历班级名单来点名。班级名单可以看作是一个集合,每个学生名字可以看作是集合中的一个元素。使用迭代器模式,你可以通过迭代器对象逐个访问学生的名字,而不需要了解班级名单的具体实现细节。
  • 遍历音乐播放列表:当我们在手机或电脑上播放音乐时,通常会创建一个播放列表。播放列表可以被视为一个集合,每首歌曲可以被视为集合中的一个元素。使用迭代器模式,我们可以通过迭代器对象逐个访问播放列表中的歌曲,进行播放、暂停或切歌等操作。

4.2 java场景

  • 集合框架中的迭代器:在Java中,集合包括List、Set、Map等等,每个集合类中都提供了一个获取迭代器的方法,例如List提供的iterator()方法、Set提供的iterator()方法等等。通过获取对应的迭代器对象,可以对集合中的元素进行遍历和访问。
  • JDBC中的ResultSet对象:在Java中,如果需要对数据库中的数据进行遍历和访问,可以使用JDBC操作数据库。JDBC中,查询结果集使用ResultSet对象来表示,通过使用ResultSet的next()方法,就可以像使用迭代器一样遍历和访问查询结果中的数据。
  • 文件读取:在Java中,我们可以使用BufferedReader类来读取文本文件。BufferedReader类提供了一个方法readLine()来逐行读取文件内容。实际上,BufferedReader在内部使用了迭代器模式来逐行读取文本文件的内容。

五、代码实现 

下面以班级名单为例,解释一下迭代器模式。

5.0 代码结构

5.1 Student——学生实体类

首先我们定义一个学生类,用来表示学生信息。

/**
 * @author Created by njy on 2023/6/25
 * 学生实体类
 */
@Data
public class Student {
    private String name;
    private Integer age;
    public Student(String name,Integer age){
        this.age=age;
        this.name=name;
    }
}

5.2 StudentIterator——抽象迭代器(Iterator)

接下来创建一个抽象迭代器(学生迭代器)并继承Iterator接口(java.util包下的Iterator)

import java.util.Iterator;
/**
 * @author Created by njy on 2023/6/25
 * 抽象迭代器(Iterator):学生迭代器
 * 实现Iterator接口
 * 负责定义访问和遍历元素的接口,例如提供hasNext()和next()方法。
 */
public interface StudentIterator extends Iterator<Student> {
}

5.3 StudentListIterator——具体迭代器(Concrete iterator)

在这个具体迭代器中,实现抽象迭代器,重写hashNext()和next()方法。

/**
 * @author Created by njy on 2023/6/25
 * 具体迭代器(Concrete iterator):
 * 实现抽象迭代器定义的接口,负责实现对元素的访问和遍历。
 */
public class StudentListIterator implements StudentIterator{
    private List<Student> students;
    private int index;

    public StudentListIterator(List<Student> students) {
        this.students = students;
        this.index = 0;
    }

    //检查是否还有下一个元素
    @Override
    public boolean hasNext() {
        return (index < students.size());
    }

    //返回下一个元素
    @Override
    public Student next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        Student student = students.get(index);
        index++;
        return student;
    }
}

5.4 StudentAggregate——抽象聚合器(Aggregate)

定义一个抽象聚合器,并定义一个iterator()方法,用于创建具体的迭代器对象。

/**
 * @author Created by njy on 2023/6/25
 * 抽象聚合器(Aggregate):学生聚合器
 * 提供创建迭代器的接口,例如可以定义一个iterator()方法。
 */
public interface StudentAggregate {
    //用于创建具体的迭代器对象
    StudentIterator iterator();
    void add(Student student);
}

5.5 ClassList——具体聚合器(Concrete Aggregate)

实现抽象聚合器定义的接口,负责创建具体的迭代器对象。

/**
 * @author Created by njy on 2023/6/25
 * 具体聚合器(ConcreteAggregate):班级列表
 * 实现抽象聚合器定义的接口,负责创建具体的迭代器对象,并返回该对象。
 */
public class ClassList implements StudentAggregate{
    private List<Student> students = new ArrayList<>();

    //创建迭代器对象
    @Override
    public StudentIterator iterator() {
        return new StudentListIterator(students);
    }

    //向班级名单中添加学生信息
    @Override
    public void add(Student student) {
        students.add(student);
    }
}

5.6 testIterator

/**
 * @author Created by njy on 2023/6/25
 * 迭代器模式测试类
 */
@SpringBootTest
public class TestIterator {
    @Test
    void testIterator(){
        ClassList classList = new ClassList();
        // 添加学生信息
        classList.add(new Student("张三", 18));
        classList.add(new Student("李四", 19));
        classList.add(new Student("王五", 20));
        // 获取迭代器,遍历学生信息
        StudentIterator iterator = classList.iterator();
        while(iterator.hasNext()) {
            Student student = iterator.next();
            System.out.println("学生姓名:" + student.getName() + ",学生年龄:" + student.getAge());
        }
    }

}

六、总结

  • 迭代器模式提供了一种统一的方式来遍历集合对象中的元素。
  • 它将遍历操作封装到一个独立的迭代器对象中,使得我们可以按照特定的方式访问集合中的元素。
  • 迭代器模式将集合对象和遍历操作分离开来,提高了代码的灵活性和可维护性。
  • 使用迭代器模式可以让我们用相同的方式遍历不同类型的集合对象,而不需要了解集合的内部结构。

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

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

相关文章

threejs官方demo学习:模型加载

前言 案例太多了&#xff0c;考虑了一下&#xff0c;实际项目中有可能用的情况一般就是加载模型&#xff0c;然后对模型进行一些操作。因此打算好好看一下关于模型加载的案例&#xff0c;其他案例就不看了。 模型加载并改变材质 <script lang"ts" setup> im…

基于 FPGA 的单脉冲技术:算法设计(附源码)

一、前言 本例显示了开发单脉冲技术的工作流程的前半部分&#xff0c;其中信号使用数字下变频&#xff08;DDC&#xff09;进行下变频。本例中的模型适合在FPGA上实现。本示例重点介绍单脉冲技术的设计&#xff0c;以估计物体的方位角和仰角。 示例的第二部分是基于FPGA的单脉冲…

【C++】hash:unordered_map和unordered_set的底层结构

hash 哈希概念哈希冲突哈希函数哈希冲突的两种解决方法之闭散列哈希冲突的两种解决方法之开散列开散列和闭散列的比较 哈希概念 在c98中还并没有提出哈希这样的结构&#xff0c;只有以红黑树为底层结构的map&#xff0c;set系列&#xff0c;这样使得查询时的效率 l o g 2 N lo…

c语言修炼第二章--分支与循环

目录 前言 2.1分支语句 2.1.1什么是语句 2.2分支语句 2.2.1if语句的语法形式 2.2.2悬空else问题 2.2.3if书写形式的对比 2.3switch语句 2.3.1switch的语法形式 2.3.2 switch与break的关系 2.3.3 switch与default的关系 前言 小伙伴们端午安康吖&#xff01;今天我们…

Mac菜单栏快捷开关 One Switch

One Switch是一款简单易用的 macOS 应用程序&#xff0c;它可以帮助用户快速地切换和管理 Mac 电脑的各种系统设置。这款应用程序提供了一个干净简洁的界面&#xff0c;让用户可以快速地启用或禁用诸如 Wi-Fi、蓝牙、Night Shift、暗色模式、Do Not Disturb 等功能。用户可以通…

建立无需build的vue单页面应用SPA框架

vue、react这种前端渲染的框架&#xff0c;比较适合做SPA&#xff08;Single Page Application&#xff09;。如果用ejs做SPA&#xff0c;js代码控制好全局变量冲突不算严重&#xff0c;但dom元素用jquery操作会遇到很多的名称上的冲突&#xff08;tag、id、name&#xff09;。…

运动蓝牙耳机怎么选、好用的运动蓝牙耳机推荐

在快节奏的现代生活中&#xff0c;运动成为了释放压力、保持健康和放松身心的重要方式。跑步、健身、骑行等各类运动成为了人们日常生活中不可或缺的一部分。然而&#xff0c;一场精彩的运动体验离不开动感的音乐伴奏。为了满足人们对高品质音乐的追求&#xff0c;一款出色的运…

nvm安装、管理多个node版本

1、官网下载nvm https://github.com/coreybutler/nvm-windows/releases 2、解压ZIP&#xff0c;双击nvm-setup.exe(假如以前安装了node.js&#xff0c;把以前的卸载了再安装nvm) 3、安装nvm 注意&#xff1a;这一步的nodejs目录需要手动创建 4、安装完毕&#xff0c;设置下载镜…

OpenCV动态人物识别代码

动态人物识别代码 int main() {// 打开视频文件或摄像头VideoCapture cap("vtest.avi");// VideoCapture cap(0); // 使用默认摄像头if (!cap.isOpened()){std::cout << "无法打开视频文件或摄像头流" << std::endl;return -1;}// 读取第一帧…

幽灵依赖是什么,pnpm出现的意义,使用pnpm创建一个vue3项目

什么是幽灵依赖&#xff08;幻影依赖&#xff09; 比如我们创建一个全新的vue3项目 然后我们正常地通过npm install来下载依赖 然后我们发现&#xff0c;node_ modules文件夹下的很多依赖&#xff0c;我们在package.json中明明没去声明却都下载下来了 那么这些没声明却下载…

SQL-游标-查询

/***DB版本&#xff1a;SQL Server 2022***/ --切换数据库 use MyDatabase--创建游标(scroll&#xff1a;滚动游标) declare mycur cursor scroll for select EmpNo from Employee--打开游标 open mycur --提取第一行 fetch first from mycur --提取最后一行 fetch last from m…

ansible自动化安装及简单操作

目录 一、运行机制 二、安装 1.下载ansible 2.配置免密 3.修改配置文件 4.创建主机清单 5.远程安装 6.远程卸载 一、运行机制 Ansible&#xff1a; ansible的核心模块 Host Inventory&#xff1a;主机清单&#xff0c;也就是被管理的主机列表 Playbooks&…

实战打靶集锦-021-glasgowsmile

提示&#xff1a;本文记录了博主的一次曲折的打靶经历。 目录 1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 手工访问4.2 目录枚举4.3 手工探查4.4 搜索EXP4.5 joomlascan4.6 用户猜测与密码爆破4.7 构建反弹shell 5. 提权5.1 优化shell5.2 枚举系统信息5.3 探查/etc/pass…

虚拟机VMware+Ubuntu配置DPDK环境并运行Helloworld

虚拟机VMwareUbuntu配置DPDK环境并运行Helloworld 文章目录 虚拟机VMwareUbuntu配置DPDK环境并运行Helloworld安装虚拟机虚拟机中安装DPDK运行Helloworld 首先需要强调的是&#xff0c;版本的影响很大&#xff0c;有可能会因为版本不匹配而导致无法成功配置DPDK环境。 安装虚拟…

【Leetcode -637.二叉树的层平均值 -671.二叉树中第二小的节点】

Leetcode Leetcode -637.二叉树的层平均值Leetcode -671.二叉树中第二小的节点 Leetcode -637.二叉树的层平均值 题目&#xff1a;给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10^(- 5) 以内的答案可以被接受。 示例 1&#xff1…

TCP服务器的C#实现

1、TCP实现类 internal class TcpServer{public Socket ServerSocket { get; set; }public Dictionary<string,Socket> Sockets { get; set; } new Dictionary<string,Socket>();public byte[] SendBuffer { get; set; }public byte[] ReceiveBuffer { get; set; …

Qt消息对话框

一、头文件及类型 #include<QMessageBox> 二、错误、信息、提示、警告演示 错误对话框 QMessageBox::critical(this,"critical","错误"); 信息对话框 QMessageBox::information(this,"info","信息"); 提问对话框 if(QMessageBo…

发布自己的第一个抖音小程序

结构与微信小程序一样 内嵌H5网页&#xff0c;适用于任何平台&#xff0c;同样也是使用web-view组件 <web-view src"https://some-domain/some/path"></web-view> 相比起来&#xff0c;它比微信小程序更加简化&#xff0c;开发会更方便了。 API查询地…

超越Java 7,迎接Java 8时代!掌握这些新特性提升你的编程技能!

大家好&#xff0c;我是小米&#xff0c;一个热衷于技术分享的小伙伴。今天&#xff0c;我将向大家介绍Java 8中的一些新特性。Java 8作为一次重大更新&#xff0c;引入了许多令人激动的新功能&#xff0c;让我们的编码变得更加简洁高效。接下来&#xff0c;我们将详细介绍这些…

【暂时解决】radio单选框的change事件执行两次

项目场景&#xff1a; 简单的单选框场景 选择国内地区&#xff0c;省市县的下拉框就显示&#xff0c;选择国外地区就隐藏。 问题描述 当我使用radio的change事件时&#xff0c;会执行两次 javascript&#xff1a; $(input[typeradio][nameoptionsRadios]).change(function …