JAVA设计模式之迭代器模式详解

news2024/11/24 20:33:00

迭代器模式

1 迭代器模式介绍

迭代器模式是我们学习一个设计时很少用到的、但编码实现时却经常使用到的行为型设计模式。在绝大多数编程语言中,迭代器已经成为一个基础的类库,直接用来遍历集合对象。在平时开发中,我们更多的是直接使用它,很少会从零去实现一个迭代器。

迭代器模式(Iterator pattern)又叫游标(Cursor)模式,它的原始定义是:迭代器提供一种对容器对象中的各个元素进行访问的方法,而又不需要暴露该对象的内部细节。

在这里插入图片描述

在软件系统中,容器对象拥有两个职责: 一是存储数据,而是遍历数据.从依赖性上看,前者是聚合对象的基本职责.而后者是可变化的,又是可分离的.因此可以将遍历数据的行为从容器中抽取出来,封装到迭代器对象中,由迭代器来提供遍历数据的行为,这将简化聚合对象的设计,更加符合单一职责原则

2 迭代器模式原理

迭代器模式结构图
在这里插入图片描述

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

  • 抽象集合(Aggregate)角色:用于存储和管理元素对象, 定义存储、添加、删除集合元素的功能,并且声明了一个createIterator()方法用于创建迭代器对象。
  • 具体集合(ConcreteAggregate)角色:实现抽象集合类,返回一个具体迭代器的实例。
  • 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、next() 等方法。
    • hasNext()函数用于判断集合中是否还有下一个元素
    • next() 函数用于将游标后移一位元素
    • currentItem() 函数,用来返回当前游标指向的元素
  • 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对集合对象的遍历,同时记录遍历的当前位置。

3 迭代器模式实现

/**
 * 迭代器接口
 **/
public interface Iterator<E> {

    //判断集合中是否有下一个元素
    boolean hasNext();

    //将游标后移一位元素
    void next();

    //返回当前游标指定的元素
    E currentItem();
}

/**
 * 具体迭代器
 **/
public class ConcreteIterator<E> implements Iterator<E>{

    private int cursor; //游标

    private ArrayList<E> arrayList; //容器

    public ConcreteIterator(ArrayList<E> arrayList) {
        this.cursor = 0;
        this.arrayList = arrayList;
    }

    @Override
    public boolean hasNext() {
        return cursor != arrayList.size();
    }

    @Override
    public void next() {
        cursor++;
    }

    @Override
    public E currentItem() {
        if(cursor >= arrayList.size()){
            throw new NoSuchElementException();
        }
        return arrayList.get(cursor);
    }
}

public class Test01 {


    public static void main(String[] args) {

        ArrayList<String> names = new ArrayList<>();
        names.add("lisi");
        names.add("zhangsan");
        names.add("wangwu");

        Iterator<String> iterator = new ConcreteIterator(names);
        while(iterator.hasNext()){
            System.out.println(iterator.currentItem());
            iterator.next();
        }

        /**
         * 使用ArrayList集合中的iterator()方法获取迭代器
         * 将创建迭代器的方法放入集合容器中,这样做的好处是对客户端封装了迭代器的实现细节.
         */
        java.util.Iterator<String> iterator1 = names.iterator();
        while(iterator1.hasNext()){
            System.out.println(iterator1.next());
            iterator.next();
        }
    }
}

4 迭代器模式应用实例

为了帮助你更好地理解迭代器模式,下面我们还是通过一个简单的例子给大家演示一下

/**
 * 抽象迭代器 IteratorIterator
 **/
public interface IteratorIterator<E> {

    void reset();   //重置为第一个元素
    E next();   //获取下一个元素
    E currentItem();    //检索当前元素
    boolean hasNext();  //判断是否还有下一个元素存在
}


/**
 * 抽象集合 ListList
 **/
public interface ListList<E> {

    //获取迭代器对象的抽象方法(面向接口编程)
    IteratorIterator<E> Iterator();
}

/**
 * 主题类
 **/
public class Topic {

    private String name;

    public Topic(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * 具体迭代器
 **/
public class TopicIterator implements IteratorIterator<Topic> {

    //Topic数组
    private Topic[] topics;

    //记录存储位置
    private int position;

    public TopicIterator(Topic[] topics) {
        this.topics = topics;
        position = 0;
    }

    @Override
    public void reset() {
        position = 0;
    }

    @Override
    public Topic next() {
        return topics[position++];
    }

    @Override
    public Topic currentItem() {
        return topics[position];
    }

    @Override
    public boolean hasNext() {
        if(position >= topics.length){
            return false;
        }
        return true;
    }
}

/**
 * 具体集合类
 **/
public class TopicList implements ListList<Topic> {

    private Topic[] topics;

    public TopicList(Topic[] topics) {
        this.topics = topics;
    }

    @Override
    public IteratorIterator<Topic> Iterator() {
        return new TopicIterator(topics);
    }
}

public class Client {

    public static void main(String[] args) {

        Topic[] topics = new Topic[4];
        topics[0] = new Topic("topic1");
        topics[1] = new Topic("topic2");
        topics[2] = new Topic("topic3");
        topics[3] = new Topic("topic4");

        TopicList topicList = new TopicList(topics);
        IteratorIterator<Topic> iterator = topicList.Iterator();

        while(iterator.hasNext()){
            Topic t = iterator.next();
            System.out.println(t.getName());
        }
    }
}

5 迭代器模式总结

  1. 迭代器的优点:
  • 迭代器模式支持以不同方式遍历一个集合对象,在同一个集合对象上可以定义多种遍历方式. 在迭代器模式中只需要用一个不同的迭代器来替换原有的迭代器,即可改变遍历算法,也可以自己定义迭代器的子类以支持新的遍历方式.
  • 迭代器简化了集合类。由于引入了迭代器,在原有的集合对象中不需要再自行提供数据遍历等方法,这样可以简化集合类的设计。
  • 在迭代器模式中,由于引入了抽象层,增加新的集合类和迭代器类都很方便,无须修改原有代码,满足 “基于接口编程而非实现” 和 “开闭原则” 的要求。
  1. 迭代器的缺点:
  • 由于迭代器模式将存储数据和遍历数据的职责分离,增加了类的个数,这在一定程度上增加了系统的复杂性。
  • 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展.`
  1. 使用场景
  • 减少程序中重复的遍历代码

    对于放入一个集合容器中的多个对象来说,访问必然涉及遍历算法。如果我们不将遍历算法封装到容器里(比如,List、Set、Map 等),那么就需要使用容器的人自行去实现遍历算法,这样容易造成很多重复的循环和条件判断语句出现,不利于代码的复用和扩展,同时还会暴露不同容器的内部结构。而使用迭代器模式是将遍历算法作为容器对象自身的一种“属性方法”来使用,能够有效地避免写很多重复的代码,同时又不会暴露内部结构。

  • 当需要为遍历不同的集合结构提供一个统一的接口时或者当访问一个集合对象的内容而无须暴露其内部细节的表示时。

    迭代器模式把对不同集合类的访问逻辑抽象出来,这样在不用暴露集合内部结构的情况下,可以隐藏不同集合遍历需要使用的算法,同时还能够对外提供更为简便的访问算法接口。

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

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

相关文章

联想thinkpad-E450双系统升级记

早期笔记本联想thinkpad-E450双系统 大约16年花4000多大洋&#xff0c;买了一台thinkpad-E450屏幕是16寸本&#xff0c;有AMD独立显卡&#xff0c;i5cpu&#xff0c;4G内存。 . 后来加了一个同型号4G内存组成双通道&#xff0c; . 加了一个三星固态500G&#xff0c; . 换了一个…

如何编写高效的可复用程序

子程序、FB 、FC等的相关内容还可以查看下面文章链接&#xff1a; https://rxxw-control.blog.csdn.net/article/details/124524693https://rxxw-control.blog.csdn.net/article/details/124524693 1、FB和FC编程的优点 待续.....

前置++与后置++

a相当于a的值在其中运算 a

02 动力云客之登陆界面

1. 前端登录界面 需求样式: 1. 自定义登录页面装配到main.js src下新建一个文件夹view, view下新建一个Vue Component , 名为LoginView.vue , 并选择options API Composition API用于复杂页面. 生成的LoginView.vue文件 <script> export default {//组件的名字nam…

【2024.02.11】定时执行专家 V6.9 龙年春节版 - 下载地址更新日志

目录 ◆ 最新版下载链接 ◆ 软件更新日志 – TimingExecutor Full Change Log ▼2024-02-11 V6.9 ▼2023-06-16 V6.8.2 ▼2023-02-27 V6.7 ▼ 2023-01-23 V6.6 ▼ 2023-01-20 V6.5 ▼ 2022-12-25 V6.4 ▼ 2022-11-15 V6.3 ▼ 2022-10-01 V6.2 ▼ 2022-07-…

苍穹外卖实操笔记六---缓存商品,购物车功能

苍穹外卖实操笔记六—缓存商品&#xff0c;购物车功能 一.缓存菜品 可以使用redis进行缓存&#xff1b;另外&#xff0c;在实现缓存套餐时可以使用spring cache提高开发效率&#xff1b;   通过缓存数据&#xff0c;降低访问数据库的次数&#xff1b; 使用的缓存逻辑&#…

uniapp微信小程序开发踩坑日记:Pinia持久化

如果你使用过Pinia&#xff0c;那你应该知道Pinia持久化插件&#xff1a;https://prazdevs.github.io/pinia-plugin-persistedstate/zh/ 但由于官方文档提供的说明并不是针对小程序开发&#xff0c;所以我们在使用这个插件实现uniapp小程序开发中Pinia持久化会出现问题 我在C…

ubuntu中尝试安装ros2

首先&#xff0c;ubuntu打开后有个机器人栏目&#xff0c;打开后&#xff0c;有好多可选的&#xff0c;看了半天 ,好像是博客&#xff0c;算了&#xff0c;没啥关系&#xff0c;再看看其他菜单 这些都不是下载链接。先不管&#xff0c;考虑了一下&#xff0c;问了ai&#xff…

Z-Stack一直卡在HAL_BOARD_INIT();

原因是Debugger没有配置好&#xff0c;因为默认是Simulator&#xff0c;不是TI的驱动&#xff0c;所以仿真出现一直卡在 HAL_BOARD_INIT(); 的情况&#xff0c;解决方法就是将Simulator改为Texas Instruments 改成下面的样子

Unity Meta Quest MR 开发(四):使用 Scene API 和 Depth API 实现深度识别和环境遮挡

文章目录 &#x1f4d5;教程说明&#x1f4d5;Scene API 实现遮挡&#x1f4d5;Scene API 实现遮挡的缺点&#x1f4d5;Depth API 实现遮挡⭐导入 Depth API⭐修改环境配置⭐添加 EnvironmentDepthOcclusion 预制体⭐给物体替换遮挡 Shader⭐取消现实手部的遮挡效果 此教程相关…

如何入门AI Agent?

随着chatgpt问世&#xff0c;大模型已经在加速各行各业的变革&#xff0c;这是我之前对AI Agent行业的粗浅判断。 下面给大家介绍一下如何制作AI Agent&#xff0c;我会用我开发的全赞AI为例子进行简要的介绍&#xff0c;下面是一种工具型AI Agent的框架图 这是一个大量使用工具…

vue中watch和computed的不同

第076个 查看专栏目录: VUE ------ element UI Vue.js 中的 watch 和 computed 都是用于监听数据变化并执行相应操作的选项&#xff0c;但它们的使用场景和优劣势有所不同。 两者区别 watch 用于监听一个或多个数据属性的变化&#xff0c;并在变化时执行相应的处理函数。 它…

unity学习案例总结

动态标签 GitHub - SarahMit/DynamicLabel3D: Simple dynamic labels for a 3D Unity scene

Jumpserver教程01:部署jumpserver

Jumpserver教程 注&#xff1a; 本教程由羞涩梦整理同步发布&#xff0c;本人技术分享站点&#xff1a;blog.hukanfa.com 转发本文请备注原文链接&#xff0c;本文内容整理日期&#xff1a;2024-02-11 csdn 博客名称&#xff1a;五维空间-影子&#xff0c;欢迎关注 简要说明…

单片机学习笔记---AT24C02(I2C总线)

目录 有关储存器的介绍 存储器的简介 存储器简化模型 AT24C02介绍 AT24C02引脚及应用电路 I2C总线介绍 I2C电路规范 开漏输出模式和弱上拉模式 其中一个设备的内部结构 I2C通信是怎么实现的 I2C时序结构 起始条件和终止条件 发送一个字节 接收一个字节 发送应答…

【深度优先搜索】【树】【图论】2973. 树中每个节点放置的金币数目

作者推荐 视频算法专题 本博文涉及知识点 深度优先搜索 树 图论 分类讨论 LeetCode2973. 树中每个节点放置的金币数目 给你一棵 n 个节点的 无向 树&#xff0c;节点编号为 0 到 n - 1 &#xff0c;树的根节点在节点 0 处。同时给你一个长度为 n - 1 的二维整数数组 edges…

计网day1

RTT&#xff1a;往返传播时延&#xff08;越大&#xff0c;游戏延迟&#xff09; 一.算机网络概念 网络&#xff1a;网样的东西&#xff0c;网状系统 计算机网络&#xff1a;是一个将分散得、具有独立功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功…

课堂秩序要求有哪些内容

你是否曾经疑惑&#xff0c;为什么有些课堂总是秩序井然&#xff0c;而有些则混乱不堪&#xff1f;作为一位经验丰富的老师&#xff0c;我想告诉你&#xff0c;课堂秩序不仅仅是学生安静听讲那么简单&#xff0c;它背后涉及到许多关键因素&#xff0c;直接影响着教学质量和学习…

Unity学习笔记(零基础到就业)|Chapter04:C#篇补充到Unity篇过渡

Unity学习笔记&#xff08;零基础到就业&#xff09;&#xff5c;Chapter02:C#篇补充到Unity篇过渡 前言C#总结补充1.值类型和引用类型有什么区别&#xff0c;他们在值的传递上分别有怎样的特性2.string是引用类型&#xff0c;但是他对外表现出值类型的特性&#xff0c;为什么&…

【BIAI】Lecture 14 - Sleep and Dreaming

Sleep and Dreaming 专业词汇 pons 延髓 parietal cortex 顶叶皮层 limbic system 边缘系统 temporal cortex 颞叶皮层 dorsolateral prefrontal cortex 背外侧前额叶皮层 pineal gland 松果体 Suprachiasmatic Nucleus 视交叉上核 课程大纲 Sleep stages awake无眼动睡眠&am…