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

这篇具有很好参考价值的文章主要介绍了Java 设计模式——迭代器模式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.概述

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

2.结构

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

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

3.案例实现

【例】定义一个可以存储学生对象的容器对象,将遍历该容器的功能交由迭代器实现,其类图如下:
Java 设计模式——迭代器模式,Java 设计模式,Java,迭代器模式,设计模式

具体实现代码如下:
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;
    }
    
    @Override
    public 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;
    }
    
    @Override
    public boolean hasNext() {
        return position < list.size();
    }
    
    @Override
    public 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<>();
    
    @Override
    public void addStudent(Student stu) {
        list.add(stu);
    }
    
    @Override
    public void removeStudent(Student stu) {
        list.remove(stu);
    }
    
    //获取迭代器对象
    @Override
    public 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];
        }
		
		//删除当前元素
		public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }        

        //...
}

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

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

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 的实现类就可以了。文章来源地址https://www.toymoban.com/news/detail-569665.html

到了这里,关于Java 设计模式——迭代器模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式 ~ 迭代器模式

    迭代器是一种设计模式,提供了一种顺序访问集合或容器中元素的方法,无需暴露集合的内部结构,for 循环并不是迭代器模式 ,forEach 是最简易的迭代器。 以下函数实现了 next 方法,调用该方法返回集合中的下一个元素 value 表示当前迭代到的元素值 done 表示迭代是否已经结

    2024年02月16日
    浏览(37)
  • 设计模式-迭代器模式

      迭代器模式(Iterator Design Pattern),也叫作游标模式(Cursor Design Pattern)。它用来遍历集合对象。这里说的“集合对象”也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,比如数组、链表、树、图、跳表。迭代器模式将集合对象的遍历操作从集合类中拆

    2024年02月05日
    浏览(53)
  • 设计模式——迭代器模式

    它提供一种方法访问一个容器对象中各个元素,而又不需要暴露该对象的内部细节。 迭代器是为容器服务的,能容纳元素的对象可以称为容器,例:List、Set、Map 迭代器模式(Iterator Pattern)已经是没落的设计模式,常用的容器基本都有成熟稳定的实现,基本不会再去单独写一

    2024年02月13日
    浏览(41)
  • 设计模式:迭代器模式

    迭代器模式的示例可以涵盖各种数据结构的遍历,包括数组、列表、树、图等。下面是一些不同场景下迭代器模式的示例及其代码实现。 示例 1: 数组遍历 使用迭代器模式遍历数组。 示例 2: 二叉树的深度优先遍历 二叉树的深度优先遍历(使用栈实现)。 示例 3: 分页遍历 在

    2024年04月11日
    浏览(49)
  • 设计模式浅析(十) ·设计模式之迭代器&组合模式

    日常叨逼叨 java设计模式浅析,如果觉得对你有帮助,记得一键三连,谢谢各位观众老爷😁😁 案例 有两家门店,门店A呢只提供早餐,门店B呢只提供午餐,有一天这两家店铺想要进行合并,一起做大做强,再创辉煌。 合并后呢,对于菜单的定制存在了一定的问题: 门店A的

    2024年04月11日
    浏览(49)
  • 设计模式——迭代器模式15

    迭代器模式提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。 设计模式,一定要敲代码理解 迭代器模式将数据存储和数据遍历的职责进行分离。但针对不同结构的迭代对象,迭代方式需进行添加。 代码下载

    2024年04月15日
    浏览(46)
  • 设计模式行为型——迭代器模式

    目录 迭代器模式的定义 迭代器模式的实现 迭代器模式角色 迭代器模式类图 迭代器模式代码实现 迭代器模式的特点 优点 缺点 使用场景 注意事项         迭代器模式(Iterator Pattern)属于行为型模式,其提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对

    2024年02月14日
    浏览(36)
  • 行为型设计模式——迭代器模式

    迭代器模式也是非常的简单, 定义如下: 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 相信大家都使用过类似下面的迭代器: 如果在你的项目中需要对一个自定义的集合进行迭代遍历,那么迭代器模式是非常需要学习的。迭代器模式主

    2024年01月18日
    浏览(42)
  • 设计模式学习笔记 - 设计模式与范式 -行为型:9.迭代器模式(上):相比直接遍历集合数据,使用迭代器模式有哪些优势?

    上篇文章,我们学习了状态模式。状态模式是状态机的一种实现方式。它通过将事件触发的状态转移和动作执行,拆分到不同的状态类中,以此来避免状态机类中的分支判断逻辑,应对状态机类代码的复杂性。 本章,学习另外一种行为型设计模式,迭代器模式。它用来遍历集

    2024年04月15日
    浏览(57)
  • C++设计模式之迭代器模式

    【声明】本题目来源于卡码网(https://kamacoder.com/) 【提示:如果不想看文字介绍,可以直接跳转到 C++编码部分 】         --什么是迭代器模式(第19种设计模式)          迭代器模式 是⼀种 行为设计模式 ,是⼀种使⽤频率⾮常⾼的设计模式,在各个语⾔中都有应用,

    2024年01月24日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包