一. 什么是迭代器模式
- 迭代器模式: 用来遍历集合对象 (集合在这里也叫做容器)
- 迭代器模式, 将对集合的遍历操作和集合本身拆分出来, 将遍历操作放到迭代器类中, 让两者的职责更单一.
- 为什么要将遍历操作和集合本身拆分出来 - 简化客户端调用的复杂性
有些数据结构的遍历很复杂, 不是像数组简单的通过角标就能遍历. 比如"图"的遍历, 就可以分为深度优先遍历(DFS)和广度优先遍历(BFS). 这些代码如果交由调用方自己编写会造成调用难度巨大; 如果放在集合类内部实现又会增加结合类的复杂性; 应对复杂性的办法就是拆分. 因此, 使用迭代器模式的好处是:- 迭代器模式封装集合内部的复杂数据结构,开发者不需要了解如何遍历,直接使用容器提供的迭代器即可;
- 迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一;
- 迭代器模式让添加新的遍历算法更加容易,更符合开闭原则。除此之外,因为迭代器都实现自相同的接口,在开发中,基于接口而非实现编程,替换迭代器也变得更加容易。
- 为什么要将遍历操作和集合本身拆分出来 - 简化客户端调用的复杂性
二. 迭代器模式的实现
-
结构
为了达到面向接口而非面向实现编程, 又抽象出了容器接口和迭代器接口- 容器:
- 容器接口
- 容器实现类
- 跌迭代器:
- 迭代器接口
- 迭代器实现类
- 容器:
-
实现
- 迭代器: 采用组合的方式, 让迭代器可以访问要迭代的容器
// 迭代器接口 interface Iterator<E> { boolean hasNext(); void next(); E currentItem(); } // 数组跌迭代器 class ArrayIterator<E> implements Iterator<E> { private int cursor; private ArrayList<E> arrayList; ArrayIterator(ArrayList<E> arrayList) { this.cursor = 0; this.arrayList = arrayList; } @Override boolean hasNext() { return cursor != arrayList.size(); //注意这里,cursor在指向最后一个元素的时候,hasNext()仍旧返回true。 } @Override void next() { cursor++; } @Override E currentItem() { if (cursor >= arrayList.size()) { throw new NoSuchElementException(); } return arrayList.get(cursor); } }
- 容器: 提供方法生成迭代器
// 容器接口 interface List<E> { Iterator iterator(); //...省略其他接口函数... } // 数组容器 class ArrayList<E> implements List<E> { //... Iterator iterator() { return new ArrayIterator(this); } //...省略其他代码 }
- 调用方: 可以 new 一个迭代器, 也可以从容器获取迭代器
class Demo { static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("xzg"); names.add("wang"); names.add("zheng"); // 自己生成迭代器 Iterator<String> iterator = new ArrayIterator(names); // 从集合获取迭代器 Iterator<String> iterator = names.iterator(); while (iterator.hasNext()) { System.out.println(iterator.currentItem()); iterator.next(); } } }