设计模式详解(十七)——迭代子模式

迭代子模式简介

迭代子模式定义
迭代子模式,也称为迭代器模式,是一种对象行为模式。它的定义是:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。在迭代子模式中,迭代子是一个对象,它知道如何遍历集合,并且跟踪它当前在集合中的位置。迭代子提供了一种统一的方式来访问集合中的元素,无论集合的具体类型如何。迭代子模式的核心思想是将遍历集合的行为从集合本身中分离出来,这样集合就可以专注于自己的数据结构,而遍历集合的逻辑可以被封装在迭代子中。
迭代子模式在实际开发中经常用于处理集合类的数据,例如数组、列表、树等。它提供了一种灵活的方式来遍历集合中的元素,同时也使得代码更易于维护和扩展。通过将遍历集合的逻辑抽象出来,迭代子模式使得集合和遍历逻辑可以相互独立地变化,从而提高了代码的灵活性和可维护性。

迭代子模式包含以下角色:

  1. 抽象迭代子(Iterator):这是一个抽象角色,它定义了遍历元素所需的接口。迭代器的主要职责是提供一种方法来访问聚合对象中的元素,同时隐藏了聚合对象的内部表示。迭代器通常包含诸如获取下一个元素、判断是否还有更多元素等操作。
  2. 具体迭代子(ConcreteIterator):这个角色实现了迭代器接口,负责具体的遍历逻辑。它通常维护一个指向当前元素的游标,并在遍历过程中更新该游标的位置。具体迭代器需要了解聚合对象的内部结构,以便正确遍历其元素。
  3. 聚合对象(Aggregate):这也是一个抽象角色,它定义了创建迭代器对象的接口。聚合对象通常包含一组元素,并提供一个方法来获取一个迭代器对象,以便外部可以遍历这些元素。聚合对象不需要暴露其内部表示,只需提供获取迭代器的接口即可。
  4. 具体聚合对象(ConcreteAggregate):这个角色实现了聚合接口,负责创建具体的迭代器对象。具体聚合通常包含一组具体的元素,并实现了获取迭代器的方法,该方法返回一个与具体聚合对象相匹配的迭代器实例。

迭代子模式优缺点:
优点:

  1. 多态迭代:它为不同的聚合结构提供了一致的遍历接口,使得一个迭代接口可以访问不同的聚集对象。
  2. 简化聚集对象接口:通过将遍历逻辑封装在迭代器中,聚合对象的接口可以更加简洁和专一。聚合对象只需要提供一个创建迭代器的方法,而无需暴露其内部结构和遍历逻辑。
  3. 元素迭代功能多样化:每个聚集对象都可以提供一个或多个不同的迭代器,这使得同种元素聚合结构可以有不同的迭代行为。
  4. 提高代码的可读性和可维护性:使用迭代子模式可以使代码更加清晰和易于理解。遍历逻辑被封装在迭代器中,使得聚合对象的代码更加专注于其数据结构和核心功能。同时,由于迭代器的独立性,修改遍历逻辑时不会影响到聚合对象的代码,提高了代码的可维护性。
  5. 支持多种遍历方式:迭代子模式允许在不修改聚合对象的前提下增加新的遍历方式。通过实现不同的迭代器,可以方便地支持正序、逆序、过滤等多种遍历需求。

缺点:

  1. 实现复杂性:对于简单的遍历,如数组或有序列表,使用迭代子模式可能会增加实现的复杂性。所以对于小型项目或简单的数据结构,使用迭代子模式可能过于复杂和繁琐。
  2. 类的数量增加:每次新增一个集合类,都需要增加相应的迭代器类,这可能会导致类的个数成对增加,增加了系统的复杂性,增加代码的复杂性和管理成本。
  3. 性能开销:在某些情况下,使用迭代子模式可能会引入一些性能开销。由于每次遍历都需要创建新的迭代器对象,这可能会增加内存消耗和对象创建/销毁的开销。然而,这种开销通常是可以接受的,尤其是在需要灵活遍历聚合对象的情况下。

使用场景

  1. 访问聚合对象内容而不暴露内部表示:当需要访问一个聚合对象的内容,但不希望直接暴露其内部数据结构时,可以使用迭代子模式。通过迭代器,可以在不了解聚合对象内部实现细节的情况下,遍历并访问其元素。
  2. 为聚合对象提供多种遍历方式:当需要为聚合对象提供不同的遍历方式时,如正向遍历、逆向遍历、跳跃遍历等,迭代子模式非常适用。通过实现不同的迭代器,可以轻松支持多种遍历需求。
  3. 统一遍历不同聚合结构:当需要为不同类型的聚合结构提供一个统一的遍历接口时,迭代子模式可以发挥作用。无论是列表、栈、树还是图等数据结构,都可以通过迭代器进行统一的遍历操作,从而简化代码和提高可维护性。
  4. 隐藏集合对象的内部结构:当需要隐藏集合对象的内部结构,只提供统一的遍历接口时,迭代子模式非常有用。这样,外部代码可以透明地访问集合内部的数据,而无需了解集合的具体实现细节。

以下举一个迭代子模式的例子:
下面通过一个简单的例子来演示。

创建抽象聚合对象(Aggregate)

/*** 抽象聚合对象:定义了创建迭代器对象的接口*/
public interface Aggregate {public void add(String str);public void remove(String str);public Iterator getIterator();
}

创建具体聚合对象(ConcreteAggregate)

import java.util.ArrayList;
import java.util.List;/*** 具体聚合对象:实现了聚合接口,负责创建具体的迭代器对象*/
public class ConcreteAggregate implements Aggregate {private List<String> list=new ArrayList<String>();public void add(String str){list.add(str);}public void remove(String str){list.remove(str);}public Iterator getIterator(){return(new ConcreteIterator(list));}}

创建抽象迭代子(Iterator)

/*** 抽象迭代子:抽象角色,它定义了遍历元素所需的接口*/
public interface Iterator {String first();String next();boolean hasNext();
}

创建具体迭代子(ConcreteIterator)

import java.util.List;/*** 具体迭代子:实现了迭代器接口,负责具体的遍历逻辑*/
public class ConcreteIterator implements Iterator {private List<String> list;private int index;public ConcreteIterator(List<String> list){this.list=list;}// 判断列表对象中是否还有参数public boolean hasNext(){if(index < list.size()-1){return true;}else{return false;}}// 获取对象列表中第一个参数public String first(){index = 0;String str = list.get(index);;return str;}// 获取对象列表中下一个参数public String next(){String str = null;if(this.hasNext()){str=list.get(++index);}return str;}
}

创建客户端(Client)

public class Client {public static void main(String[] args) {Aggregate aggregate = new ConcreteAggregate();aggregate.add("篮球");aggregate.add("足球");aggregate.add("羽毛球");aggregate.add("网球");System.out.println("添加后的聚合对象内容有:");Iterator iterator = aggregate.getIterator();while (iterator.hasNext()) {String str = iterator.next();System.out.println(str);}System.out.println("===================");String str = iterator.first();System.out.println("聚合对象里第一个内容是:" + str);}
}

输出结果如下所示:

添加后的聚合对象内容有:
足球
羽毛球
网球
===================
聚合对象里第一个内容是:篮球

在上述例子中,我们定义了一个迭代子模式,包括抽象聚合对象、具体聚合对象、抽象迭代子和具体迭代子。Aggregate类中定义了添加元素、移除元素和获取迭代器对象的接口。在这个例子中,它包含一个添加字符串的add方法,一个移除字符串的remove方法,以及一个返回迭代器对象的getIterator方法。ConcreteAggregate 类实现了 Aggregate 接口,并使用一个 ArrayList 来存储元素。Iterator类中定义了迭代器的行为,定义了遍历元素所需的接口,包括first(获取第一个元素)、next(获取下一个元素)和hasNext(判断是否还有更多元素)方法。ConcreteIterator 类实现了 Iterator 接口,并提供了具体的遍历逻辑。客户端代码 (Client 类) 则是创建了一个 ConcreteAggregate对象,添加了一些元素,并通过迭代器遍历这些元素。

总而言之:
迭代子模式是一种行为设计模式,通过将遍历集合对象的行为封装在迭代子对象中,实现了遍历与集合对象的分离。它包括抽象迭代子、具体迭代子、聚合对象和具体聚合对象等角色。优点包括提高代码灵活性、模块化和隐藏集合对象内部结构;缺点是增加了代码复杂度和可能降低性能。适用于需要统一遍历接口、隐藏集合对象细节、提供多种遍历方式等场景。迭代子模式能够使代码更易维护、灵活,并提供一种统一的遍历方式,是一种常用的设计模式。
总之,迭代子模式通过将遍历集合的行为从集合对象中分离出来,实现了更好的封装和更灵活的设计。


以上代码下载请点击该链接:https://github.com/Yarrow052/Java-package.git

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

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

相关文章

别再把ERP吹上天了,在中国根本没几家企业用得起来

ERP系统无疑具有诸多优势&#xff0c;然而&#xff0c;其在中国多年的应用实效如何&#xff0c;各界看法不一&#xff0c;尚无定论。 历经长达20余年的信息化探索&#xff0c;华为直至2016年才达成了“流程基本顺畅&#xff0c;账目与实际相符”的目标&#xff08;详见华为轮值…

张大哥笔记:如何选择一个好项目?

互联网已经改变了我们的日常生活&#xff0c;使我们可以便捷地获取信息&#xff0c;更快地完成工作&#xff0c;更有效地进行沟通&#xff0c;并且可以让我们更容易地获得服务。随着技术的发展&#xff0c;互联网将继续改变我们的生活.... 有时候我们会感叹&#xff0c;互联网发…

群组分析方法

目录 1.什么是群组分析方法 2.基本原理 3.群组分析方法分类 3.1.层次方法 3.2.划分方法 3.3.密度基方法 ​​​​​​​3.4.模型基方法 4.群组评估 5.应用步骤 1.什么是群组分析方法 群组分析&#xff08;Cluster Analysis&#xff09;是数据分析中的一种重要方法&…

VMWare vmdk文件非常大解决

你如果发现你的虚拟机占用了几百个GB的空间想要变小&#xff0c;在我使用电脑中有一个虚拟机放在了D盘的vm7.9文件夹中。D盘总容量为1TB,但是扯淡的是一个虚拟机占用了600多个GB空间&#xff0c;我按照下面流程执行了最终变为了使用200多GB。 虚拟机经过长时间使用以及各种操作…

北航计算机软件技术基础课程作业笔记【5】

题目 (文章一周后公开~) sort 1.快排算法 核心思路:选取(一般是)当前数组第一个元素作为中间值mid,将数组按照比mid小/大分为两半,再对子数组进行同样操作(二叉树前序遍历) 具体操作:主要是分2半那里,可以巧妙一些地来遍历,所以用到了left和right指针(重合时就遍…

【Redis】面试题汇总

Redis什么是Redis、使用场景有哪些Redis 为什么这么快&#xff1f;Redis 数据类型及使用场景五种常见的 Redis 数据类型是怎么实现&#xff1f;Redis是单线程吗Redis 采用单线程为什么还这么快&#xff1f;Redis 如何实现数据不丢失&#xff1f;Redis 如何实现服务高可用&#…

基于Linux的Ncurse库的贪吃蛇项目

贪吃蛇项目的意义 承上启下&#xff1a;从C语言基础的学习&#xff1a;数据结构链表基础、C变量、流程控制、函数、指针、结构体等。过渡到Linux系统编程&#xff1a;文件编程、进程、线程、通信、第三方等。 Linux终端图形库curses curses的名字起源于"cursor optimiz…

Oracle Analytics BIEE 操作方法(五)仪表盘导出“区域”不换行也不合并居中的方法

1 分析 取消所有区域内列格式里面的换行 2 仪表盘 点击“工具” 打印和导出选项 设置固定列宽&#xff08;范围是&#xff1a;0-300&#xff09;

Day22 SSH远程管理服务

sshd服务&#xff0c;系统自带&#xff0c;默认开机自启运行 云/物理服务器的安全组和防火墙默认放行该端口 软件包&#xff1a;openssh-server&#xff08;服务端&#xff09;&#xff1b;openssh-client&#xff08;客户端&#xff09;&#xff1b; 格式&#xff1a;ssh I…

【学习笔记二十七】EWM存储类型控制

一、EWM存储类型控制概述 Storage control 是用来决定仓库产品移动时所需要的流程步骤。它的目的是用来处理基于仓库物理布局及仓库流程所要求的复杂的上架和下架流程步骤。 仓库里常见的操作步骤有:Picking、Packing、Staging、Loading、Putaway、Unloading、Counting、Quali…

Jetbrains Fleet这十个快捷键,效率提高50倍

当我们无法解决一段感情中的问题 就会选择解决这段感情 如果真诚不得到回应 那么再热情的人 也会沉默 很多人对你感兴趣 却没有人执着于你 我们知道任何一款牛批的IDE 都是有很多快捷键的&#xff0c;但是我们没有superpower &#xff0c;不能记住所有的快捷键。 所以下面…

LightGBM训练过程中的‘No further splits with positive gain‘警告解析

在使用LightGBM进行机器学习任务时&#xff0c;你可能会遇到这样的警告信息&#xff1a;[LightGBM] [Warning] No further splits with positive gain, best gain: -…。这个警告信息意味着在构建决策树的过程中&#xff0c;算法没有找到任何能够带来正增益&#xff08;即提高模…

CSS基础:4类组合选择器以及5个注意事项

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

【Fastadmin】富文本编辑器图片绝对路径改为相对路径

目录 1.场景需求 2.解决方案:把绝对路径改为相对路径存储 首先找到安装的编辑器js文件 3.api获取的时候加入域名实现逻辑 1.安装phpQuery库来处理HTML内容 2.创建一个包含HTML内容的字符串变量$content。 3.使用phpQuery库创建一个新的HTML文档,并将$content作为文档内…

成功密码期刊投稿简介

《成功密码》综合版是由国家新闻出版总署批准&#xff0c;江西省教育厅主管的正规期刊&#xff0c;"以培养担当民族复兴大任的时代新人为着眼点&#xff0c;强化教育引导、实践养成、制度保障"&#xff0c;倡导教育研究的学术水准&#xff0c;注重理论与实践的有机结…

StringBuilder 和 StringBuffer:Java字符串处理的利器

作为准备面试的程序员&#xff0c;你一定知道在Java中字符串处理是一个非常重要的话题。而StringBuilder和StringBuffer作为Java中常用的字符串处理工具&#xff0c;是你必须要掌握的技术之一。 本文将深入探讨StringBuilder和StringBuffer的特点、区别以及在实际开发中的应用…

java spring security oauth2 动态 修改当前登录用户的基础信息以及权限2.0(无需重新登录)

两年前写过一篇动态修改角色和权限当时表述的不是很全面 比如如何修改其他用户权限 修改用户信息没有效果等 再写一篇 如何修改其他用户权限 不管如何改变实际需求就是获取用户token,不管是当前用户还是所有用户 当前用户的token可以通过上下文拿到,而其他用户的token该如何拿…

Delphi 的Show和ShowModal

Show没有返回值是一个过程&#xff0c;焦点可以不在当前窗体&#xff1b; 用法新建一个子窗体&#xff1a; 主窗体&#xff1a; 调用&#xff0c;引用子窗体的单元 调用 showmodal是一个函数有返回值&#xff0c;窗体的处理结果&#xff0c;且只能聚焦到当前窗体 效果都能展示…

尺取法知识点讲解

一、固定长度的情况&#xff1a; 最小和(sum) 输入N个数的数列&#xff0c;所有相邻的M个数的和共有N-M1个&#xff0c;求其中的最小值。 输入格式 第1行&#xff0c;2个整数N&#xff0c;M&#xff0c;范围在[3…100000]&#xff0c;N>M。 第2行&#xff0c;有N个正…

C++多线程系列——std::future | std::promise

获得线程执行任务的结果 在 C 11 之前&#xff0c;想要从线程返回执行任务的结果&#xff0c;可以通过指针来完成。 void fun(int x, int y, int* ans, std::condition_variable &cv) {// 模拟求值之前的准备工作this_thread::sleep_for(3s);*ans x y;cv.notify_one();…