迭代器设计模式详解与实例

迭代器模式

迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。

迭代器模式结构

在这里插入图片描述

  1. 迭代器 (Iterator) 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。

  2. 具体迭代器 (Concrete Iterators) 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。

  3. 集合 (Collection) 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。

  4. 具体集合 (Concrete Collections) 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。

  5. 客户端 (Client) 通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。

    客户端通常不会自行创建迭代器, 而是会从集合中获取。 但在特定情况下, 客户端可以直接创建一个迭代器 (例如当客户端需要自定义特殊迭代器时)。

迭代器模式通用代码:

//抽象迭代器
interface Iterator{
//遍历下一个元素
public Object next();
//是否遍历到尾部
public boolean hasNext();
//删除当前指向元素
public boolean remove();
}

//具体迭代器
public class ConcreteIterator implements Iterator{
private Vector vector = new Vector();
private int cursor= 0;//当前游标
public ConcreteIterator(Vector _vector){
 this.vector = _vector;
}

//是否遍历到尾部
public boolean hasNext(){
     if(this.cursor==this.vector.size()){
        return false;//false 代表到尾部
    }else{
        return true;
    }
}

//遍历下一个元素
public Object next(){
    Object result = null;
    if(this.hasNext()){
        result = this.vector.get(this.cursor++);
    }else{
        result = null;
    }
    return result;
} 

//删除当前指向元素
public boolean remove() {
    this.vector.remove(this.cursor);
    return true; 
}
}

//抽象容器
interface Aggregate {
    Iterator createIterator();
}

// 具体聚合类
class ConcreteAggregate implements Aggregate {
    private Vector vector = new Vector();

    public void add(Object obj) {
        vector.add(obj);
    }

    public Object get(int index) {
        return vector.get(index);
    }

    public int size() {
        return vector.size();
    }

    @Override
    public Iterator createIterator() {
        return new ConcreteIterator(vector);
    }
}

// 客户端示例
public class Client {
    public static void main(String[] args) {
        ConcreteAggregate aggregate = new ConcreteAggregate();
        aggregate.add("Item 1");
        aggregate.add("Item 2");
        aggregate.add("Item 3");

        Iterator iterator = aggregate.createIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

迭代器模式适用场景

  1. 当集合背后为复杂的数据结构, 且你希望对客户端隐藏其复杂性时 (出于使用便利性或安全性的考虑), 可以使用迭代器模式。

    迭代器封装了与复杂数据结构进行交互的细节, 为客户端提供多个访问集合元素的简单方法。 这种方式不仅对客户端来说非常方便, 而且能避免客户端在直接与集合交互时执行错误或有害的操作, 从而起到保护集合的作用。

  2. 使用该模式可以减少程序中重复的遍历代码。

    重要迭代算法的代码往往体积非常庞大。 当这些代码被放置在程序业务逻辑中时, 它会让原始代码的职责模糊不清, 降低其可维护性。 因此, 将遍历代码移到特定的迭代器中可使程序代码更加精炼和简洁。

  3. 如果你希望代码能够遍历不同的甚至是无法预知的数据结构, 可以使用迭代器模式。

    该模式为集合和迭代器提供了一些通用接口。 如果你在代码中使用了这些接口, 那么将其他实现了这些接口的集合和迭代器传递给它时, 它仍将可以正常运行。
    在这里插入图片描述

识别方法: 迭代器可以通过导航方法 (例如 nextprevious等) 来轻松识别。 使用迭代器的客户端代码可能没有其所遍历的集合的直接访问权限。

迭代器模式优缺点

优点:

  • 单一职责原则。 通过将体积庞大的遍历算法代码抽取为独立的类, 你可对客户端代码和集合进行整理。

  • 开闭原则。 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码。

  • 你可以并行遍历同一集合, 因为每个迭代器对象都包含其自身的遍历状态。

  • 相似的, 你可以暂停遍历并在需要时继续。

缺点:

  • 如果你的程序只与简单的集合进行交互, 应用该模式可能会矫枉过正。

  • 对于某些特殊集合, 使用迭代器可能比直接遍历的效率低。

练手题目

题目描述

小明是一位老师,在进行班级点名时,希望有一个学生名单系统,请你实现迭代器模式提供一个迭代器使得可以按顺序遍历学生列表。

输入描述

第一行是一个整数 N (1 <= N <= 100), 表示学生的数量。

接下来的 N 行,每行包含一个学生的信息,格式为 姓名 学号

输出描述

输出班级点名的结果,即按顺序遍历学生列表,输出学生的姓名和学号

在这里插入图片描述

题解

迭代器模式代码:

import java.util.*;

// 迭代器接口
interface StudentIterator {
    boolean hasNext();
    Student next();
}

// 具体迭代器类
class ConcreteStudentIterator implements StudentIterator {
    private List<Student> studentList;
    private int index = 0;

    public ConcreteStudentIterator(List<Student> studentList) {
        this.studentList = studentList;
    }

    @Override
    public boolean hasNext() {
        return index < studentList.size() && studentList.get(index) != null;
    }

    @Override
    public Student next() {
        return studentList.get(index++);
    }
}

// 学生列表系统接口
interface StudentListSystem {
    void addStudent(String name, String id);
    String getStudentInfo();
    StudentIterator iterator();
}

// 学生类
class Student implements StudentListSystem {
    private String name;
    private String id;
    private List<Student> studentList;

    public Student() {
        this.studentList = new ArrayList<>();
    }

    public Student(String name, String id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public void addStudent(String name, String id) {
        this.studentList.add(new Student(name, id));
    }

    @Override
    public String getStudentInfo() {
        return name + " " + id;
    }

    @Override
    public StudentIterator iterator() {
        return new ConcreteStudentIterator(this.studentList);
    }
}


public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        StudentListSystem studentList = new Student();

        int n = scanner.nextInt();
        scanner.nextLine();

        for (int i = 0; i < n; i++) {
            String[] studentInfo = scanner.nextLine().split(" ");
            studentList.addStudent(studentInfo[0], studentInfo[1]);
        }

        StudentIterator iterator = studentList.iterator();
        while (iterator.hasNext()) {
            Student student = (Student) iterator.next();
            System.out.println(student.getStudentInfo());
        }

        scanner.close();
    }
}

Java 内置的 List 接口的 iterator() 方法实现。

import java.util.*;

// 学生类
class Student {
    String name;
    String id;

    Student(String name, String id) {
        this.name = name;
        this.id = id;
    }

    String getInfo() {
        return name + " " + id;
    }
}

// 学生列表系统
class StudentListSystem {
    private List<Student> students = new ArrayList<>();

    void addStudent(String name, String id) {
        students.add(new Student(name, id));
    }

    Iterator<Student> iterator() {
        return students.iterator();
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        StudentListSystem studentList = new StudentListSystem();

        int n = scanner.nextInt();
        scanner.nextLine(); 

        for (int i = 0; i < n; i++) {
            String[] s = scanner.nextLine().split(" ");
            studentList.addStudent(s[0], s[1]);
        }

        Iterator<Student> iterator = studentList.iterator();
        while (iterator.hasNext()) {
            Student student = iterator.next();
            System.out.println(student.getInfo());
        }
        scanner.close();
    }
}
  • 26
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天马行空的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值