行为型模式 - 迭代器模式(Iterator Pattern)

简介: 行为型模式 - 迭代器模式(Iterator Pattern)

前言

一、迭代器模式概述

迭代器模式定义: 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

二、迭代器模式结构

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

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

三、迭代器模式案例实现

【例】定义一个可以存储学生对象的容器对象,将遍历该容器的功能交由迭代器实现,涉及到的类如下:

网络异常,图片无法展示
|
代码如下:

定义迭代器接口,声明hasNext、next方法
public interface StudentIterator {  
   boolean hasNext();  
   Student next();  
}
定义具体的迭代器类,重写所有的抽象方法
public class StudentIteratorImpl implements StudentIterator {  
   private List<Student> list;  
   private int position = 0;  
   public StudentIteratorImpl(List<Student> list) {  
       this.list = list;  
  }  
   @Override  
   public boolean hasNext() {  
       return position < list.size();  
  }  
   @Override  
   public Student next() {  
       Student currentStudent = list.get(position);  
       position ++;  
       return currentStudent;  
  }  
}
定义抽象容器类,包含添加元素,删除元素,获取迭代器对象的方法
public interface StudentAggregate {  
   void addStudent(Student student);  
   void removeStudent(Student student);  
   StudentIterator getStudentIterator();  
}
定义具体的容器类,重写所有的方法
public class StudentAggregateImpl implements StudentAggregate {  
   private List<Student> list = new ArrayList<Student>();  // 学生列表  
   @Override  
   public void addStudent(Student student) {  
       this.list.add(student);  
  }  
   @Override  
   public void removeStudent(Student student) {  
       this.list.remove(student);  
  }  
   @Override  
   public StudentIterator getStudentIterator() {  
       return new StudentIteratorImpl(list);  
  }  
}

四、迭代器模式优缺点

  • 优点:
  • 它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。
  • 迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。
  • 在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足 “开闭原则” 的要求。
  • 缺点:
  • 增加了类的个数,这在一定程度上增加了系统的复杂性。

五、迭代器模式使用场景

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

六、JDK源码解析

迭代器模式在JAVA的很多集合类中被广泛应用,接下来看看JAVA源码中是如何使用迭代器模式的。

List<String> list = new ArrayList<>();  
Iterator<String> iterator = list.iterator(); //list.iterator()方法返回的肯定是Iterator接口的子实现类对象  
while (iterator.hasNext()) {  
   System.out.println(iterator.next());  
}

看完这段代码是不是很熟悉,与我们上面代码基本类似。单列集合都使用到了迭代器,我们以ArrayList举例来说明

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

具体的来看看 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];  
      }  
      ...  
}

这部分代码还是比较简单,大致就是在 iterator 方法中返回了一个实例化的 Iterator 对象。Itr是一个内部类,它实现了 Iterator 接口并重写了其中的抽象方法。

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

后记

喜欢我的文章的朋友点点喜欢、收藏,也欢迎朋友们评论区留下你的意见和建议,恕毅在此拜谢!


相关文章
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
523 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
(续集)记录2分钟破解知识星球验证弹窗
那我换个思路,反正网站简单,这次直接用替换的方式
1837 0
|
运维 Prometheus 监控
今天在集群中创建yaml,使用create就创建成功,apply就创建失败原因分析。
今天在集群中创建yaml,使用create就创建成功,apply就创建失败原因分析。
|
存储 关系型数据库 MySQL
MySQL基础命令及使用示例
这些基础命令构成了与MySQL数据库交互的核心,理解并掌握它们对于进行有效的数据库操作至关重要。在实际使用中,建议结合实际案例和需求来练习这些命令,以加深理解和提高效率。
278 3
|
人工智能 文件存储 对象存储
Stable Diffusion 模型库,AIGC 画风任你选
Stable Diffusion(简称 SD)模型库包含写实、国漫、科技等几十种风格。可以让用户一键转存到自己的存储空间,而后直接挂载到 PAl 或 FC 下进行推理和训练。无需复杂漫长的下载和上传步骤,即可获得多种模型的使用体验,实现云上 AIGC 的快速搭建。
52462 22
Stable Diffusion 模型库,AIGC 画风任你选
|
测试技术 程序员
W模型和瀑布模型与“V”模式开发模型有何异同?
W模型和瀑布模型与“V”模式开发模型有何异同?
430 1
|
网络协议 Java
在Java中使用TCP协议搭建一个简单的客户端
如何在Java中使用TCP协议搭建一个简单的客户端
456 2
|
前端开发
超文本标记语言(HTML)简介
超文本标记语言(HTML)简介
304 3
|
定位技术 数据安全/隐私保护
3分钟部署 我的世界(Minecraft) 联机服务
如何通过计算巢快速部署《我的世界(Minecraft)》联机服务
3分钟部署 我的世界(Minecraft) 联机服务
|
存储 搜索推荐 算法
【排序】软考笔记:简要回顾下常见的几种排序算法
【排序】软考笔记:简要回顾下常见的几种排序算法
290 0
【排序】软考笔记:简要回顾下常见的几种排序算法