设计模式第16讲——迭代器模式(Iterator)

  • Post author:
  • Post category:其他



目录


一、什么是迭代器模式


二、角色组成


三、 优缺点


四、应用场景


4.1 生活场景


4.2 java场景


五、代码实现


5.0 UML类图


5.1 Student——学生实体类


5.2 StudentIterator——抽象迭代器(Iterator)


5.3 StudentListIterator——具体迭代器(Concrete iterator)


5.4 StudentAggregate——抽象聚合器(Aggregate)


5.5 ClassList——具体聚合器(Concrete Aggregate)


5.6 testIterator


六、总结


一、什么是迭代器模式

迭代器模式是一种

行为型

设计模式,它提供了一种

统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式

。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。

二、角色组成

  • 抽象迭代器(Iterator):定义了遍历聚合对象所需的方法,包括

    hashNext()



    next()

    方法等,用于遍历聚合对象中的元素。
  • 具体迭代器(Concrete Iterator):它是实现迭代器接口的具体实现类,负责具体的遍历逻辑。它保存了当前遍历的位置信息,并可以根据需要向前或向后遍历集合元素。
  • 抽象聚合器(Aggregate): 一般是一个接口,提供一个iterator()方法,例如java中的Collection接口,List接口,Set接口等。
  • 具体聚合器(ConcreteAggregate):就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。

三、 优缺点


优点:

  • 简化了集合类的接口,使用者可以更加简单地遍历集合对象,而不需要了解集合内部结构和实现细节。
  • 将集合和遍历操作解耦,使得我们可以更灵活地使用不同的迭代器来遍历同一个集合,根据需求选择不同的遍历方式。
  • 满足开闭原则,如果需要增加新的遍历方式,只需实现一个新的具体迭代器即可,不需要修改原先聚合对象的代码。


缺点:

  • 具体迭代器实现的算法对外不可见,因此不利于调试和维护。
  • 对于某些小型、简单的集合对象来说,使用迭代器模式可能会显得过于复杂,增加了代码的复杂性。

四、应用场景

4.1 生活场景

  • 遍历班级名单:假设你是一名班主任,你需要遍历班级名单来点名。班级名单可以看作是一个集合,每个学生名字可以看作是集合中的一个元素。使用迭代器模式,你可以通过迭代器对象逐个访问学生的名字,而不需要了解班级名单的具体实现细节。
  • 遍历音乐播放列表:当我们在手机或电脑上播放音乐时,通常会创建一个播放列表。播放列表可以被视为一个集合,每首歌曲可以被视为集合中的一个元素。使用迭代器模式,我们可以通过迭代器对象逐个访问播放列表中的歌曲,进行播放、暂停或切歌等操作。

4.2 java场景

  • 集合框架中的迭代器:在Java中,集合包括List、Set、Map等等,每个集合类中都提供了一个获取迭代器的方法,例如List提供的iterator()方法、Set提供的iterator()方法等等。通过获取对应的迭代器对象,可以对集合中的元素进行遍历和访问。
  • JDBC中的ResultSet对象:在Java中,如果需要对数据库中的数据进行遍历和访问,可以使用JDBC操作数据库。JDBC中,查询结果集使用ResultSet对象来表示,通过使用ResultSet的next()方法,就可以像使用迭代器一样遍历和访问查询结果中的数据。
  • 文件读取:在Java中,我们可以使用BufferedReader类来读取文本文件。BufferedReader类提供了一个方法readLine()来逐行读取文件内容。实际上,BufferedReader在内部使用了迭代器模式来逐行读取文本文件的内容。

五、代码实现

下面以班级名单为例,解释一下迭代器模式。

  • 抽象迭代器:StudentIterator
  • 具体迭代器:StudentListIterator
  • 抽象聚合器:StudentAggregate
  • 具体聚合器:ClassList

5.0 UML类图

5.1 Student——学生实体类

首先我们定义一个学生类,用来表示学生信息。

/**
 * @author Created by njy on 2023/6/25
 * 学生实体类
 */
@Data
public class Student {
    private String name;
    private Integer age;
    public Student(String name,Integer age){
        this.age=age;
        this.name=name;
    }
}

5.2 StudentIterator——抽象迭代器(Iterator)

接下来创建一个抽象迭代器(学生迭代器)并继承Iterator接口(java.util包下的Iterator)

import java.util.Iterator;
/**
 * @author Created by njy on 2023/6/25
 * 抽象迭代器(Iterator):学生迭代器
 * 实现Iterator接口
 * 负责定义访问和遍历元素的接口,例如提供hasNext()和next()方法。
 */
public interface StudentIterator extends Iterator<Student> {
}

5.3 StudentListIterator——具体迭代器(Concrete iterator)

在这个具体迭代器中,实现抽象迭代器,重写hashNext()和next()方法。

/**
 * @author Created by njy on 2023/6/25
 * 具体迭代器(Concrete iterator):
 * 实现抽象迭代器定义的接口,负责实现对元素的访问和遍历。
 */
public class StudentListIterator implements StudentIterator{
    private List<Student> students;
    private int index;

    public StudentListIterator(List<Student> students) {
        this.students = students;
        this.index = 0;
    }

    //检查是否还有下一个元素
    @Override
    public boolean hasNext() {
        return (index < students.size());
    }

    //返回下一个元素
    @Override
    public Student next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        Student student = students.get(index);
        index++;
        return student;
    }
}

5.4 StudentAggregate——抽象聚合器(Aggregate)

定义一个抽象聚合器,并定义一个iterator()方法,用于创建具体的迭代器对象。

/**
 * @author Created by njy on 2023/6/25
 * 抽象聚合器(Aggregate):学生聚合器
 * 提供创建迭代器的接口,例如可以定义一个iterator()方法。
 */
public interface StudentAggregate {
    //用于创建具体的迭代器对象
    StudentIterator iterator();
    void add(Student student);
}

5.5 ClassList——具体聚合器(Concrete Aggregate)

实现抽象聚合器定义的接口,负责创建具体的迭代器对象。

/**
 * @author Created by njy on 2023/6/25
 * 具体聚合器(ConcreteAggregate):班级列表
 * 实现抽象聚合器定义的接口,负责创建具体的迭代器对象,并返回该对象。
 */
public class ClassList implements StudentAggregate{
    private List<Student> students = new ArrayList<>();

    //创建迭代器对象
    @Override
    public StudentIterator iterator() {
        return new StudentListIterator(students);
    }

    //向班级名单中添加学生信息
    @Override
    public void add(Student student) {
        students.add(student);
    }
}

5.6 testIterator

/**
 * @author Created by njy on 2023/6/25
 * 迭代器模式测试类
 */
@SpringBootTest
public class TestIterator {
    @Test
    void testIterator(){
        ClassList classList = new ClassList();
        // 添加学生信息
        classList.add(new Student("张三", 18));
        classList.add(new Student("李四", 19));
        classList.add(new Student("王五", 20));
        // 获取迭代器,遍历学生信息
        StudentIterator iterator = classList.iterator();
        while(iterator.hasNext()) {
            Student student = iterator.next();
            System.out.println("学生姓名:" + student.getName() + ",学生年龄:" + student.getAge());
        }
    }

}

六、总结

  • 迭代器模式提供了一种统一的方式来遍历集合对象中的元素。
  • 它将遍历操作封装到一个独立的迭代器对象中,使得我们可以按照特定的方式访问集合中的元素。
  • 迭代器模式将集合对象和遍历操作分离开来,提高了代码的灵活性和可维护性。
  • 使用迭代器模式可以让我们用相同的方式遍历不同类型的集合对象,而不需要了解集合的内部结构。



版权声明:本文为weixin_45433817原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。