Java 设计模式——迭代器模式

目录

  • 1.概述
  • 2.结构
  • 3.案例实现
    • 3.1.抽象迭代器
    • 3.2.具体迭代器
    • 3.3.抽象聚合
    • 3.4.具体聚合
    • 3.5.测试
  • 4.优缺点
  • 5.使用场景
  • 6.JDK 源码解析——Iterator

1.概述

迭代器模式 (Iterator Pattern) 是一种行为型设计模式,它提供一种顺序访问聚合对象(如列表、集合等)中的元素,而无需暴露聚合对象的内部表示。迭代器模式将遍历逻辑封装在一个迭代器对象中,使得我们可以使用统一的方式遍历不同类型的聚合对象,同时也可以简化客户端代码。

2.结构

迭代器模式主要包含以下角色:

  • 抽象聚合 (Aggregate) 角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口。
  • 具体聚合 (ConcreteAggregate) 角色:实现抽象聚合类,返回一个具体迭代器的实例。
  • 抽象迭代器 (Iterator) 角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()next() 等方法。
  • 具体迭代器 (Concretelterator) 角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

3.案例实现

【例】定义一个可以存储学生对象的容器对象,将遍历该容器的功能交由迭代器实现,其类图如下:
在这里插入图片描述

具体实现代码如下:
Student.java

public class Student {private String name;private String number;public Student() {}public Student(String name, String number) {this.name = name;this.number = number;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", number='" + number + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}
}

3.1.抽象迭代器

StudentIterator.java

//抽象迭代器角色接口
public interface StudentIterator {//判断是否还有元素boolean hasNext();//获取下一个元素Student next();
}

3.2.具体迭代器

StudentIteratorImpl.java

//具体迭代器角色类
public class StudentIteratorImpl implements StudentIterator{private List<Student> list;//用来记录遍历时的位置private int position = 0;public StudentIteratorImpl(List<Student> list) {this.list = list;}@Overridepublic boolean hasNext() {return position < list.size();}@Overridepublic Student next() {//从集合中或者去指定位置的元素Student currentStudent = list.get(position);position++;return currentStudent;}
}

3.3.抽象聚合

StudentAggregate.java

//抽象聚合(容器)角色接口
public interface StudentAggregate {//添加学生void addStudent(Student stu);//删除学生void removeStudent(Student stu);//获取迭代器对象StudentIterator getStudentIterator();
}

3.4.具体聚合

StudentAggregateImpl.java

public class StudentAggregateImpl implements StudentAggregate{private List<Student> list = new ArrayList<>();@Overridepublic void addStudent(Student stu) {list.add(stu);}@Overridepublic void removeStudent(Student stu) {list.remove(stu);}//获取迭代器对象@Overridepublic StudentIterator getStudentIterator() {return new StudentIteratorImpl(list);}
}

3.5.测试

Client.java

public class Client {public static void main(String[] args) {//创建聚合(容器)对象StudentAggregateImpl aggregate = new StudentAggregateImpl();Student student1 = new Student("Tom", "1001");Student student2 = new Student("Mike", "1002");Student student3 = new Student("Jerry", "1003");Student student4 = new Student("Mary", "1004");//添加元素aggregate.addStudent(student1);aggregate.addStudent(student2);aggregate.addStudent(student3);aggregate.addStudent(student4);//删除元素aggregate.removeStudent(student3);//遍历聚合对象// 1.获取迭代器对象StudentIterator iterator = aggregate.getStudentIterator();// 2.遍历while (iterator.hasNext()){// 3.获取元素Student student = iterator.next();System.out.println(student.toString());}}
}

结果如下:

Student{name='Tom', number='1001'}
Student{name='Mike', number='1002'}
Student{name='Mary', number='1004'}

4.优缺点

(1)迭代器模式的优缺点如下:

  • 优点
    • 简化客户端代码:迭代器模式将遍历逻辑封装在迭代器对象中,客户端代码只需通过迭代器接口与迭代器对象交互,无需关心具体的遍历算法和聚合对象的内部结构,从而简化了客户端代码。
    • 统一遍历接口:迭代器模式提供一种统一的遍历接口,使得对不同类型的聚合对象可以使用相同的遍历方式,提供了更加灵活和通用的遍历操作。
    • 支持多种遍历方式:通过不同的迭代器实现,迭代器模式支持多种遍历方式,如顺序遍历、逆序遍历等,使得遍历操作更加灵活可变。
    • 解耦聚合对象与遍历操作:迭代器模式将遍历操作从聚合对象中分离出来,使得聚合对象的内部结构不再暴露给客户端,遵循了单一职责原则,提高了代码的可维护性和可扩展性。
  • 缺点
    • 对于某些较为复杂的聚合对象,实现迭代器可能会比较复杂,需要实现多个方法,并考虑并发访问的线程安全性,增加了代码的复杂性。
    • 当遍历的聚合对象发生变化时,需要相应地修改迭代器的实现,可能会影响到迭代器的逻辑。

(2)总体来说,迭代器模式适用于需要统一遍历接口、封装遍历逻辑、解耦聚合对象与遍历操作的场景。它可以提供更加灵活、通用和可维护的遍历操作,但在某些情况下,可能会增加代码的复杂性。因此,在使用迭代器模式时需要综合考虑具体的设计需求和项目情况。

5.使用场景

(1)迭代器模式通常适用于以下场景:

  • 需要遍历聚合对象的元素:当需要遍历并访问聚合对象中的元素,并且不希望暴露聚合对象的内部结构给客户端时,可以使用迭代器模式。它可以将遍历操作封装在迭代器中,提供一个统一的遍历接口。
  • 需要对不同类型的聚合对象使用统一的遍历方式:迭代器模式提供了一种统一的遍历接口,使得对不同类型的聚合对象可以使用相同的遍历方式。这样可以增加代码的灵活性和可维护性,使得客户端代码更加通用。
  • 需要支持多种遍历方式:如果需要支持多种遍历方式,如顺序遍历、逆序遍历等,可以通过不同的迭代器实现来实现不同的遍历方式。这样可以使遍历操作更加灵活可变。
  • 需要屏蔽聚合对象的内部实现细节:当聚合对象的内部结构较为复杂,或者不希望暴露内部结构给客户端时,可以使用迭代器模式进行封装。迭代器模式将遍历逻辑封装在迭代器对象中,客户端无需关心聚合对象的具体实现细节。
  • 需要遍历操作与聚合对象解耦:迭代器模式将遍历操作从聚合对象中分离出来,使得聚合对象的内部结构不再暴露给客户端。这样可以提高代码的可维护性和可扩展性,使遍历操作与聚合对象解耦。

(2)迭代器模式在现实生活中的应用也非常广泛,例如集合类、数据库查询结果等都可以使用迭代器模式来统一遍历操作接口。

6.JDK 源码解析——Iterator

(1)迭代器模式在 Java 的很多集合类中被广泛应用,接下来看下面的例子:

public class TestArratList {public static void main(String[] args) {List<String> list = new ArrayList<>();//添加元素list.add("1001");list.add("1002");list.add("1003");//删除元素list.remove("1003");Iterator<String> iterator = list.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}}
}

结果如下:

1001
1002

(2)看完这段代码是不是觉得很熟悉,它与我们上面的代码基本类似。单列集合都使用到了迭代器,所以现在以 ArrayList 举例来说明:

  • List:抽象聚合类;
  • ArrayList:具体的聚合类;
  • Iterator:抽象迭代器;
  • list.iterator():返回的是实现了 Iterator 接口的具体迭代器对象;

(3)具体来看看 ArrayList 的部分关键代码实现:

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {public Iterator<E> iterator() {return new Itr();}private class Itr implements Iterator<E> {int cursor;       	// 下一个要返回元素的索引int lastRet = -1; 	// 上一个返回元素的索引int expectedModCount = modCount;Itr() {}//判断是否还有元素public boolean hasNext() {return cursor != size;}//获取下一个元素public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}//...
}

(4)这部分代码大致就是在 iterator 方法中返回了一个实例化的 Iterator 对象。Itr 是一个内部类,它实现了 Iterator 接口并重写了其中的抽象方法。此外,通过下图可知 ArrayList 与 Iterable 的关系:

在这里插入图片描述

package java.lang;import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;public interface Iterable<T> {Iterator<T> iterator();default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}default Spliterator<T> spliterator() {return Spliterators.spliteratorUnknownSize(iterator(), 0);}
}

(5)当我们在使用 Java 开发的时想使用迭代器模式的话,只要让我们自己定义的容器类实现 java.util.Iterable 并实现其中的 iterator() 方法使其返回一个 java.util.Iterator 的实现类就可以了。

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

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

相关文章

使用亚马逊(AWS)云服务在S3上实现图片缩放功能(CloudFront/S3[AccessPoint/LambdaAccessPoint])

亚马逊云服务中的S3对象存储功能和国内阿里云的oss对象存储使用基本一致。但是涉及到存储内容处理时&#xff0c;两家有些差别。 比如&#xff1a;对于云存储中的图片资源&#xff0c;阿里云比较人性化对于基本的缩放裁剪功能已经帮我们封装好了&#xff0c;只需要在url地址后…

Bean 作用域与生命周期

Bean 作用域与生命周期 ​ 对于 Spring 来说&#xff0c;核心操作对象就是存和取 Bean &#xff0c;接下来就 Bean 的作用域与生命周期进行探讨。 文章目录 Bean 作用域与生命周期一、作用域的定义1.1、Bean 的6种作用域1.2、Bean作用域设置方法 二、Bean 的生命周期2.1、Bean…

postgresql还原bak

1、第一步肯定是要新建自己还原的目标数据库&#xff0c;例如&#xff1a; 2、进入postgresql的安装目录下的bin目录下 然后地址栏输入cmd进入命令 输入以下 psql -h localhost -U postgres -p 5432 -d SamsinoYardStandard_karamay -f "D:\desktop\zk\20230628.bak&quo…

verilog实现数码管静态显示

文章目录 verilog实现数码管静态显示一、任务要求二、实验代码三、仿真代码四、仿真结果五、总结 verilog实现数码管静态显示 一、任务要求 六个数码管同时间隔0.5s显示0-f。要求&#xff1a;使用一个顶层模块&#xff0c;调用计时器模块和数码管静态显示模块。 二、实验代码…

将Spring Boot项目打包部署到阿里云linux服务器

首先 你要保证自己的服务器上有java环境 如果没有可以参考我的文章 linux服务器中安装java JDK1.8版本 然后 我们打开我们的Spring Boot项目 双击 package 生命周期进行打包 打包完成之后 我们找到 target 下面会有一个jar包 然后 我们右键它 如下图操作 系统就会帮你打开它所…

OpenCV for Python 学习第四天 :通道的获取与合并

上一篇博客&#xff0c;我们学习了如何通过更快的item()和itemset()的方法访问图片&#xff0c;以及了解了图像的兴趣位置的获取方法&#xff0c;那么今天&#xff0c;我们将学习通道的处理方法&#xff0c;通过通道的拆分和合并的实例&#xff0c;让大家更好的了解咱们有关于B…

前端笔记_OAuth规则机制下实现个人站点接入qq三方登录

文章目录 ⭐前言⭐qq三方登录流程&#x1f496;qq互联中心创建网页应用&#x1f496;配置回调地址redirect_uri&#x1f496;流程分析 ⭐思路分解⭐技术选型实现&#x1f496;技术选型&#xff1a;&#x1f496;实现 ⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本…

JMeter做http接口功能测试

1. 普通的以key-value传参的get请求 e.g. 获取用户信息 添加http请求&#xff1b;填写服务器域名或IP&#xff1b;方法选GET&#xff1b;填写路径&#xff1b;添加参数&#xff1b;运行并查看结果。 2. 以Json串传参的post请求 e.g. 获取用户余额 添加http请求&#xff1b;…

设计模式-原型模式

目录 一、传统方式 二、原型模式 三、浅拷贝和深拷贝 克隆羊问题&#xff1a; 现在有一只羊tom&#xff0c;姓名为: tom,年龄为: 1&#xff0c;颜色为: 白色&#xff0c;请编写程序创建和tom羊属性完全相同的10只羊。 一、传统方式 public class Client {public static vo…

WMTS 地图切片Web服务 协议数据解析

1. WMTS 描述 WMTS(Web Map Tiles Service):地图切片Web服务。 2. 数据示例&#xff1a; arcgis online 导出的wmts xml&#xff1a; https://sampleserver6.arcgisonline.com/arcgis/rest/services/WorldTimeZones/MapServer/WMTS 内容解析&#xff1a; contents中可能包…

J2EEJSP自定义标签库01out标签if标签

目录 一.什么是标签 二.JSP自定义标签库 2.1 JSP标签库是什么 2.2 处理流程 2.3 如何自定义标签 2.4 标签类型 三.开发示例 3.1 out标签 1.创建助手类 2.编写tld&#xff08;标签库的描述&#xff09;文件&#xff0c;&#xff08;必须放在WEB-INF目录或其目录下&a…

python爬虫-获取headers(报文头)关键参数实例小记

注意&#xff01;&#xff01;&#xff01;&#xff01;某XX网站逆向实例仅作为学习案例&#xff0c;禁止其他个人以及团体做谋利用途&#xff01;&#xff01;&#xff01; 第一步&#xff1a;请求页面&#xff0c;得到响应。建议首次请求时headers内容都带着&#xff0c;调试…

react报错信息

报错信息 render函数里dom不能直接展示obj对象 取变量记得要有{} https://segmentfault.com/q/1010000009619339 这样在写的时候就已经执行方法了&#xff0c;所以此处用箭头函数&#xff08;&#xff09;》{}才会在点击时执行或者 遍历数据使用map来遍历&#xff0c;使用forea…

Docker【安装与基本使用】

【1】Docker的安装 注意&#xff1a;如果之前安装过docker其他版本&#xff0c;请删除干净。 docker-01 10.0.0.51 2G docker-02 10.0.0.52 2G docker-01 [rootdocker-01 ~]# cp -rp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime cp: overwrite ‘/etc/localtime’? …

H3C-Cloud Lab实验-OSPF配置实验

一、实验拓扑图 实验需求&#xff1a; 1、按照图示配置 IP 地址 2、按照图示分区域配置 OSPF &#xff0c;实现全网互通 3、为了路由结构稳定&#xff0c;要求路由器使用环回口作为 Router-id&#xff0c;ABR 的环回口宣告进骨干区域 4、掌握OSPF初始化流程、路由表学习的过…

el-progress组件使用,样式修改,自定义文字

正常的el-progress显示是这样的 修改后 自动计算percentage&#xff0c;format自定义显示文字 <template><div><div class"content-view"><div v-for"(item, index) in progressList" class"item-view"><el-prog…

解锁编程世界的魔法密码:探索算法的奥秘与应用

一个程序员一生中可能会邂逅各种各样的算法&#xff0c;但总有那么几种&#xff0c;是作为一个程序员一定会遇见且大概率需要掌握的算法。今天就来聊聊这些十分重要的“必抓&#xff01;”算法吧~* 一&#xff1a;引言 算法是解决问题和优化程序性能的核心&#xff0c;它是一…

你真的会用async和await么?

async函数搞懂 背景asyncawaitawait 知识点1await 知识点2await 知识点三await 知识点四await 知识点五 背景 背景就是遇到了一个比较烦人的模块&#xff0c;里面的涉及到了大量的async 和 awiat。发现大多人对这个语法糖一知半解&#xff0c;然后大量的滥用&#xff0c;整理一…

数据标注的类型有哪些?

构建像人类一样的AI或ML模型需要大量训练数据。要使模型做出决定并采取行动&#xff0c;就必须通过数据标注来训练模型&#xff0c;使其能够理解特定信息。 但是&#xff0c;什么是数据标注呢&#xff1f;数据标注是指对用于人工智能应用的数据进行分类和标注。我们必须针对特定…

Qt6 Qt Quick UI原型学习QML第二篇

Qt6 Qt Quick UI原型学习QML第二篇 界面效果QML语法语法讲解核心要素项目元素矩形元素文本元素图像元素MouseArea元素 界面效果 QML语法 import QtQuick 2.12 import QtQuick.Window 2.12Window {id: rootvisible: truewidth: 640height: 480title: qsTr("QML学习第二篇&…