软件设计 迭代器模式(high)Iterator Pattern

迭代器模式是 Java 中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,而不需要知道集合对象的底层表示。

迭代器是学习 Java 语言的基础,没有迭代器,集合类的遍历就成了问题,正是因为有迭代器的存在,才能更加优雅的使用 foreach 语法。

 

代码实现:

Java 中的增强 for 循环是使用迭代器实现的:

List<String> list = Arrays.asList("AAA", "BBB", "CCC");
// 使用 foreach 语法糖进行迭代,依次获取每一个元素
for (String s : list) {
   // 打印元素
   System.out.println(s);
}

编译之后的代码如下:

List<String> list = Arrays.asList("AAA", "BBB", "CCC");
// 这里本质是通过 List 生成的迭代器来遍历每个元素的
Iterator var2 = list.iterator();
// 判断是否还有元素可以迭代,没有就返回false
while(var2.hasNext()) {
   // 通过 next 方法得到下一个元素,每调用一次,迭代器会向后移动一位
   String s = (String)var2.next();
   // 打印元素
   System.out.println(s);
}
可以看到,当使用迭代器对 List 进行遍历时,实际上就像是在操作一个指向列表头部的指针,通过不断向后移动指针来依次获取所指向的元素。
   

image-20221213133251033

 

1.这里依照 JDK 提供的迭代器接口(JDK 已经定义好了一个迭代器的具体相关操作接口),也来设计一个迭代器:

1、定义数组集合

/**
* 数组集合<br>
* 实现 Iterable 接口表示此类是支持迭代的
*/
public class ArrayCollection<T> implements Iterable<T> {
   /**
    * 使用数组来存放数据
    */
   private final T[] array;
   /**
    * 构造器私有,自己用
    * @param array 数组
    */
   private ArrayCollection(T[] array) {
       this.array = array;
  }
   /**
    * 使用静态方法获取对象
    * @param array 数组
    * @return 数组集合对象
    * @param <T> 实体类
    */
   public static <T> ArrayCollection<T> of(T[] array) {
       return new ArrayCollection<>(array);
  }
   /**
    * 实现 iterator 方法,此方法会返回一个迭代器,用于迭代我们集合中的元素
    * @return 迭代器
    */
   @Override
   public Iterator<T> iterator() {
       return new ArrayIterator();
  }
   /**
    * 这里自定义 ArrayIterator,注意别用静态,需要使用对象中存放的数组
    */
   public class ArrayIterator implements Iterator<T> {
       // 这里通过指针表示当前的迭代位置
       private int index = 0;
       /**
        * 判断是否还有下一个元素
        * @return 结果
        */
       @Override
       public boolean hasNext() {
           // 如果指针大于或等于数组最大长度,就不能再继续了
           return index < array.length;
      }
       /**
        * 返回当前指针位置的元素并向后移动一位
        * @return
        */
       @Override
       public T next() {
           // 正常返回对应位置的元素,并将指针自增
           return array[index++];  
      }
  }
}
2、调用

// 定义数组
String[] arr = new String[]{"AAA", "BBB", "CCC", "DDD"};
// 使用数组集合处理数组
ArrayCollection<String> collection = ArrayCollection.of(arr);
// 使用 foreach 语法糖遍历,最后还是会变成迭代器调用
for (String s : collection) {
   System.out.println(s);
}
编译后的代码为:

String[] arr = new String[]{"AAA", "BBB", "CCC", "DDD"};
ArrayCollection<String> collection = ArrayCollection.of(arr);
// 首先获取迭代器,实际上就是调用我们实现的 iterator 方法
Iterator var3 = collection.iterator();
while(var3.hasNext()) {
   // 使用 next() 方法不断向下获取
   String s = (String)var3.next();
   System.out.println(s);
}
输出结果为:

AAA
BBB
CCC
DDD
这样就实现了自定义迭代器来遍历数组。

2.迭代器遍历学生list


1.学生类
package com17.diedai;

public class Student implements Comparable<Student> {

   private String name;
   private int sid;
   private int age;

   public Student(String name, int sid, int age) {
       this.name = name;
       this.sid = sid;
       this.age = age;
  }

   @Override
   public String toString() {
       return "Student{" +
               "姓名='" + name + '\'' +
               ", 学号=" + sid +
               ", 年龄=" + age +
               '}';
  }

//   比较两个相同类型的值
   @Override
   public int compareTo(Student o) {
       if (this.sid > o.sid){
           return -1;
      } else if (this.sid < o.sid){
           return 1;
      } else {
           return 0;
      }
  }
}

2.调用
package com17.diedai;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Client {
   public static void main(String[] args) {
       Student student1 = new Student("张三",1,21);
       Student student2 = new Student("李四",2,20);
       Student student3 = new Student("张三2",3,23);

       List<Student> list = new ArrayList<Student>();
       list.add(student1);
       list.add(student2);
       list.add(student3);
       Collections.sort(list);

       System.out.println("按学号由大到小排序输出:");
       Iterator i = list.iterator();
       while (i.hasNext()){
           System.out.println(i.next().toString());
      }

  }

}

3.输出结果
   
按学号排序输出:
Student{姓名='张三2', 学号=3, 年龄=23}
Student{姓名='李四', 学号=2, 年龄=20}
Student{姓名='张三', 学号=1, 年龄=21}

 

优缺点:

优点

1、它支持以不同的方式遍历一个聚合对象。

2、迭代器简化了聚合类。

3、在同一个聚合上可以有多个遍历。

4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

缺点

由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

 

使用场景:

1、访问一个聚合对象的内容而无须暴露它的内部表示。

2、需要为聚合对象提供多种遍历方式。

3、为遍历不同的聚合结构提供一个统一的接口。

 

注意:

迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

posted @ 2023-02-11 14:59  kuaiquxie  阅读(31)  评论(0编辑  收藏  举报