设计模式第9式:迭代器模式

news2025/7/16 6:26:33

前言

我们有很多种方法可以把对象集中到一个集合中,比如列表、堆栈、散列表中。每种集合都有自己的特点和使用时机,但都有一个共同的需求:用户想要遍历这些对象。同时我们并不想用户看到集合的实现,本文将讲解如何让用户遍历对象又无法窥视存储对象的方式。

正文

1、先来看一个实际案例

有2个餐厅,它们分别用列表和数组来保存各自的菜品:

public class BreakfastMenu {
	ArrayList breakfastItems;
	...
	ArrayList getBreakfastItems() {
		return breakfastItems; // 这里会暴露类内部的数据结构
	}
}
public class DinerMenu {
	MenuItem[] dinerItems;
	...

	MenuItem[] getDinerItems() {
		return dinerItems; // 这里会暴露类内部的数据结构
	}
}

我们想同时打印这2份菜单中的菜品,会变得复杂。我们需要首先拿到2个菜单类的变量,然后再用不同的方式遍历这2个变量。如果有第3份菜单,就需要三个循环来遍历。

for (int i = 0; i < breakfastItems.size(); i++) {
	MenuItem menuItem = breakfastItems.get(i);
}
for (int i = 0; i < dinerMenu.length; i++) {
	MenuItem menuItem = dinerMenu[i];
}

2、如何优化

当然有优化方法了,设计模式最重要的思想就是封装变化的部分。很明显,上面发生的变化是:由不同的集合类型所造成的遍历。我们来看看怎么封装:我们创建一个对象,称为“迭代器”(Iterator),用它来封装“遍历集合每个对象的过程”。

我们先在ArrayList上试试,我们先从菜单对象breakfastMenu获得一个菜单迭代器,用户只需要调用迭代器的hasNext()和next()方法。

Iterator iterator = breakfastMenu.createIterator();
while (iterator.hasNext()) {
	MenuItem menuItem = iterator.next();
}

再在数组上试试:

Iterator iterator = dinerMenu.createIterator();
while (iterator.hasNext()) {
	MenuItem menuItem = iterator.next(); // 和上面的遍历一模一样
}

3、迭代器模式

看来我们的优化奏效了,这就是大名鼎鼎的迭代器模式。它依赖一个叫做迭代器的接口。下面是一个最基本的迭代器接口。

interface Iterator {
	boolean hasNext(); // 集合中是否还有更多元素
	Object next(); // 返回下一个对象
}

有了这个接口,我们可以为各种集合创建迭代器。

public class DinerMenuIterator implements Iterator {
	MenuItem[] items; // 作为数组的迭代器,需要持有数组类型

	public boolean hasNext() {
		// 判断items中还有没有元素
	}
	
	public Object next() {
		// 判断items中下一个元素
	}
}

有了数组迭代器,我们就可以改写菜单类了。

public class DinerMenu {
	MenuItem[] dinerItems;
	...
	// 现在就不用返回实例对象了,避免了暴露类的内部结构
	// MenuItem[] getDinerItems() {
	//	 return dinerItems;
	// }
	
	// 现在只需要给用户返回一个迭代器对象
	public Iterator createIterator() {
		return new DinerMenuIterator(dinerItems); 
	}
}

现在我们来正式定义一下迭代器模式

迭代器提供一种顺序访问集合元素的方法,而又不暴露其内部结构。

这样做很有意义,迭代器模式把遍历元素的职责交给迭代器,而不是集合对象本身。这不仅让集合类的实现变得简洁,也可以让集合更专注于它应该关注的事情上(也就是管理对象元素)。下面是迭代器模式的类图:
在这里插入图片描述

4、单一职责

设计原则:一个类应该只有一个引起变化的原因

“内聚”这个术语用来度量一个类或模块达到单一目的或责任。当一个类或模块被设计成只支持一组相关的功能时,我们说它“高内聚”,更容易维护。

5、JDK中的迭代器模式

JDK中已经给我们提供了迭代器接口,和上面的非常类似,用法也基本一致。各种集合都通过迭代器完成遍历,我们来看下ArrayList是怎么实现的。

ArrayList中的iterator()方法返回一个迭代器对象。

public Iterator<E> iterator() {
    return new Itr();
}

Itr类是ArrayList中的内部类,大多数集合都是用内部类来实现迭代器的。

private class Itr implements Iterator<E> {
	...
	
	public boolean hasNext() {
	    ...
	}
	
	public E next() {
	    ...
	}
}

总结

迭代器模式很好,一方面提供了统一简洁的集合遍历方式,另一方面避免暴露集合内部结构。

集合遍历方式也在持续升级,后面JDK1.5又推出了“foreach”语法糖。JDK1.8又推出了forEach()方法继续简化遍历形式,请参考文章:Java8新特性:集合遍历forEach方法
,我们甚至不用请求迭代器了。

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

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

相关文章

JVM垃圾回收器详解

垃圾收集器没有在规范中进行过多的规定&#xff0c;可以由不同的厂商、不同版本的JVM来实现。由于JDK的版本处于高速迭代过程中&#xff0c;因此Java发展至今已经衍生了众多的GC版本。从不同角度分析垃圾收集器&#xff0c;可以将GC分为不同的类型。1、垃圾回收器分类1.1、按线…

国际安全领域顶会NDSS 2023录稿整理 (下)

隐私计算研习社 NDSS是网络和系统安全领域的四大顶级国际学术会议&#xff08;BIG4&#xff09;之一&#xff0c;第三十届会议于2023年2月27日到3月3日&#xff0c;在美国圣迭戈举办。本文将接着整理剩余论文&#xff0c;并对论文进行分类&#xff0c;感兴趣的小伙伴可以访问论…

【Linux】信号+再谈进程地址空间

目录 一、Linux中的信号 1、Linux中的信号 2、进程对信号的处理 3、信号的释义 二、信号的捕捉 1、信号的捕捉signal() 2、信号的捕捉sigaction() 三、信号如何产生&#xff1f; 1、kill()用户调用kill向操作系统发送信号 通过命令行参数模仿写一个kill命令 2、rais…

pinctrl和gpio子系统

一、pinctrl子系统简介Linux驱动讲究驱动分离与分层&#xff0c;pinctrl和gpio子系统就是驱动分离与分层思想下的产物&#xff0c;pinctrl子系统主要工作内容如下&#xff1a;获取设备树中的pin信息根据获取到的pin信息来设置pin的复用功能根据获取到的pin信息来设置pin的电气属…

Day914.安全认证架构演进:单块阶段 -SpringBoot与K8s云原生微服务实践

安全认证架构演进&#xff1a;单块阶段 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于安全认证架构演进&#xff1a;单块阶段的内容。 讲到安全认证的内容&#xff0c;就必然会提到两个点&#xff1a;认证 和 授权。 认证&#xff1a;我是谁授权&#xff1a;我能…

Spring中的事务@Transactional

Transactional可以添加在方法上 添加在方法上时&#xff0c;表示该方法出现了异常或者报错&#xff0c;而导致之前数据库没有进行回滚事件&#xff0c;也就是说如果在方法中&#xff0c;有报错&#xff0c;但是添加了Transactional 则会开始回滚。 Transactional 在异常被捕获…

剑指 Offer 29. 顺时针打印矩阵

剑指 Offer 29. 顺时针打印矩阵 难度&#xff1a;middle\color{orange}{middle}middle 题目描述 输入一个矩阵&#xff0c;按照从外向里以顺时针的顺序依次打印出每一个数字。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2…

【OpenCV技能树】——OpenCV基础

前言&#xff1a; &#x1f60a;&#x1f60a;&#x1f60a;欢迎来到本博客&#x1f60a;&#x1f60a;&#x1f60a; 目前正在进行 OpenCV技能树的学习&#xff0c;OpenCV是学习图像处理理论知识比较好的一个途径&#xff0c;至少比看书本来得实在。本专栏文章主要记录学习Op…

Apache apisix默认密钥漏洞(CVE-2020-13945)

目录漏洞描述影响版本漏洞复现声明&#xff1a;本文仅供学习参考&#xff0c;其中涉及的一切资源均来源于网络&#xff0c;请勿用于任何非法行为&#xff0c;否则您将自行承担相应后果&#xff0c;本人不承担任何法律及连带责任。漏洞描述 Apache APISIX 是一个动态、实时、高…

LearnOpenGL-模型加载-3.渲染模型

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject 文章目录模型加载重要代码读取3D模型递归处理结点的网格加载纹理优化程序代码Model类加载模型流程例子1&…

【运筹优化】拉格朗日松弛 次梯度算法求解整数规划问题 + Java调用Cplex实战

文章目录一、拉格朗日松弛二、次梯度算法三、案例实战一、拉格朗日松弛 当遇到一些很难求解的模型&#xff0c;但又不需要去求解它的精确解&#xff0c;只需要给出一个次优解或者解的上下界&#xff0c;这时便可以考虑采用松弛模型的方法加以求解。 对于一个整数规划问题&…

Python交通标志识别基于卷积神经网络的保姆级教程(Tensorflow)

项目介绍 TensorFlow2.X 搭建卷积神经网络&#xff08;CNN&#xff09;&#xff0c;实现交通标志识别。搭建的卷积神经网络是类似VGG的结构(卷积层与池化层反复堆叠&#xff0c;然后经过全连接层&#xff0c;最后用softmax映射为每个类别的概率&#xff0c;概率最大的即为识别…

chromium 50 chromium57 版本编译启用 widevine 功能

本实验中 chrome 版本为 57.0.2987.98 01 chromium57 在 win11 版本中启用 widevine 功能 01.01 启用 enable_widevine 选项生成 widevine 相关动态库 在chromium 57 版本中&#xff0c;编译时秩序设置 enable_widevinetrue 即可生成 widevinecdm.dll 和 widevinecdmadapter…

windows下maven更新/安装

写在前面: 我的maven学习的比较早&#xff0c;后面windows文件管理分类的时候&#xff0c;把学习用的全部在一个文件夹了&#xff0c;而这个又不好移动进去。 正好也更新一下maven的版本了&#xff0c;不过和重新安装好像差不多了。 现在写的windows的以后&#xff0c;在看看要…

若依框架部署从零开始2023版(前后端分离)

前言电脑最近重装了一次系统&#xff0c;目前什么都没有安装&#xff0c;记录一下从零开始部署前后端分离版本的若依框架系统先去官网把若依源码拉下来代码克隆若依目前已经有很多的版本了&#xff0c;因为现在开发比较流行前后端分离&#xff0c;因此这里演示前后端分离版本点…

外卖点餐系统小程序 PHP+UniAPP

一、介绍 本项目是给某大学餐厅开发的外面点餐系统&#xff0c;该项目针对校内的学生&#xff0c;配送由学校的学生负责配送。因此&#xff0c;该项目不同于互联网的外卖点餐系统。 该系统支持属于 Saas 系统&#xff0c;由平台端、商家端、用户端、以及配送端组成。 其中&a…

从功能测试进阶自动化测试,爆肝7天整理出这一份超全学习指南【附网盘资源】

因为我最近在分享自动化测试技术&#xff0c;经常被问到&#xff1a;功能测试想转自动化&#xff0c;请问应该怎么入手&#xff1f;有没有好的资源推荐&#xff1f;那么&#xff0c;接下来我就结合自己的经历聊一聊我是如何在工作中做自动化测试的。&#xff08;学习路线和网盘…

盒子拖拽效果,原生js实现

原生js实现拖拽效果 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevic…

keychron机械键盘使用感受

最近入手了一个Keychron无线机械键盘&#xff0c;跟mac本搭配起来使用&#xff0c;体验非常好。记录下使用的感受。 包装 包装很结实&#xff0c;拆开快递盒后&#xff0c;快递盒里有充气袋包裹着键盘盒&#xff0c;键盘盒塑料薄膜封装&#xff0c;没有一点的磕碰。 拆封 不仅外…

运动蓝牙耳机什么牌子好,比较好的运动蓝牙耳机推荐

现在市面上的运动蓝牙耳机越来越多&#xff0c;在选择耳机的时候应该如何入手呢&#xff1f;最重要的是需要按照自己的需求来选择&#xff0c;但在耳机的配置上不能忽视的是耳机的防水等级&#xff0c;运动耳机对防水等级的要求更高&#xff0c;这样能够更好地防御汗水浸湿耳机…