返回 导航

其他

hangge.com

Java - GoF设计模式详解17(迭代器模式)

作者:hangge | 2023-06-16 08:50

十七、迭代器模式

1,基本介绍

(1)迭代器模式(Iterator)提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
(2)该模式中包含的角色及其职责如下:
  • 抽象迭代器Iterator):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法。
  • 具体迭代器Concrete Iterator):它实现了抽象迭代器的接口,并保存遍历当前位置的状态。
  • 抽象聚合类Aggregate):它声明了创建相应迭代器对象的接口,即 createIterator() 方法。
  • 具体聚合类Concrete Aggregate):它实现了抽象聚合类的 createIterator() 方法,返回一个与该聚合对象相关的具体迭代器 Concrete Iterator 实例。

2,使用样例

(1)下面通过样例演示迭代器模式的使用。首先定义迭代器接口 Iterator,在该接口中规范了迭代器应该实现的方法。
// 迭代器接口
public interface Iterator<E> {
  // 判断在迭代器中是否还有元素
  boolean hasNext();
  // 访问迭代器中的下一个元素
  E next();
}

(2)接着定义迭代器接口 Iterator 的具体实现类 ConcreteIterator,其中定义了 list 用于访问集合中的数据,index 用于记录当前迭代器遍历到的元素位置,同时实现了在 Iterator 接口中定义的方法,以完成具体的迭代器需要实现的基础功能。
// 具体迭代器
public class ConcreteIterator<E> implements Iterator<E> {

  // 集合数据
  private List<E> list;

  //记录当前迭代器遍历到的元素位置
  private int index;

  public ConcreteIterator(List<E> list) {
    this.list = list;
  }

  @Override
  public boolean hasNext() {
    return index < list.size();
  }

  @Override
  public E next() {
    return list.get(index++);
  }
}

(3)然后定义集合接口 Aggregate,用于制定集合操作的规范。在该接口中定义了 iterator() 用于集合接口的遍历。
// 集合接口
public interface Aggregate<E> {
  // 获取迭代器
  Iterator<E> iterator();
}

(4)接着定义 Aggregate 接口实现类 ConcreteAggregateConcreteAggregate 类用于存储具体的数据并实现数据操作方法,其中,list 用于存储数据,iterator() 用于构造集合迭代器。
// 具体集合
public class ConcreteAggregate<E> implements Aggregate<E> {
  // 集合数据
  private List<E> list;

  public ConcreteAggregate(List<E> list) {
    this.list = list;
  }

  @Override
  public Iterator<E> iterator() {
    return new ConcreteIterator<>(list);
  }
}

(5)最后测试一下迭代器的使用,首先需要定义一个集合并向集合中加入数据,然后获取集合的 Iterator 迭代器并通过循环遍历集合中的数据。
public class Test {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("hangge", "google", "baidu");
    // 创建集合对象
    Aggregate<String> aggregate = new ConcreteAggregate<>(list);
    // 创建迭代器
    Iterator<String> iterator = aggregate.iterator();
    // 使用迭代器遍历元素
    while (iterator.hasNext()) {
      System.out.println(iterator.next());
    }
  }
}

附一:JDK 中的迭代器模式

(1)Java 标准库中的迭代器模式用在了 java.util.Iterator 接口和 java.util.Enumeration 接口中。大多数的集合类(例如 java.util.Listjava.util.Setjava.util.Map)都提供了 iterator() 方法来返回一个 java.util.Iterator 对象,用于遍历集合中的元素。
关于集合遍历更详细的介绍,可以参考我之前写的另一篇文章:

(2)比如我们可以使用以下代码遍历 java.util.List 中的元素:
public class Test {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("hangge");
    list.add("google");
    list.add("baidu");
    // 获取迭代器
    Iterator<String> iterator = list.iterator();
    // 使用迭代器遍历元素
    while (iterator.hasNext()) {
      String s = iterator.next();
      System.out.println(s);
    }
  }
}

附二:Spring 中的迭代器模式

(1)Spring Framework 在内部使用了迭代器模式,在一些地方使用了 java.util.Iterator 接口,这个接口提供了一种遍历集合的方法。比如 ConfigurableListableBeanFactory 类有一个 getBeanNamesIterator() 方法,该方法返回一个 Iterator<String>,可以用来遍历所有已注册的 bean 的名称。下面是一个简单的样例:
@RestController
public class HelloController {
  @Autowired
  private ConfigurableListableBeanFactory beanFactory;

  @GetMapping("/hello")
  public String hello() {
    String result = "";
    Iterator<String> iterator = beanFactory.getBeanNamesIterator();
    while (iterator.hasNext()) {
      String beanName = iterator.next();
      result += beanName + "<br>";
    }
    return result;
  }
}

(2)项目启动后,使用浏览器访问 hello 即可看得到 Spring 容器中所有注册的 bean 的名字:
评论

全部评论(0)

回到顶部