0.参考资料
1.概述
- 提供一种方法顺序访问一-个聚合对象中的各个元素, 而又不暴露(稳定)该对象的内部表示。一《设计模式》GoF (即: 通过迭代器来隔离算法和容器)
- 迭代器模式,提供一种遍历集合元素的统一接口,用一致的方法遍历集合元素,不需要知道集合对象的底层表示,即:不暴露其内部的结构。通过迭代器来隔离算法和容器
1.1动机
1. 在软件构建过程中,集合对象内部结构常常变化各异。但对于这些集合对象,我们希望在不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素;同时这种"透明遍历”也为“同一种算法在多种集合对象上进行操作”提供了可能。 1. 使用面向对象技术将这种遍历机制抽象为"迭代器对象”, 为“应对变化中的集合对象”提供了一种优雅的方式。 1. 如果我们的集合元素是用不同的方式实现的,有数组,还有链表等,当客户端要遍历这些集合元素的时候就要使用多种遍历方式,而且还会暴露元素的内部结构,可以考虑使用迭代器模式解决。
1.2结构
-  -  - 角色与职责分析 - Iterator :迭代器接口,是系统提供,含抽象的 hasNext(), next() - ConcreteIterator: 具体的迭代器类,管理对应的具体数据类型的迭代 - Aggregate:一个统一的聚合接口, 将客户端和具体聚合解耦 - ConcreteAggreage: 具体的聚合持有对象集合,并提供一个方法,返回一个迭代器,该迭代器可以正确遍历(该聚合类的数据)集合 - Client :客户端,通过 Iterator 和Aggregate 依赖子类
2.要点总结
宏观架构
1. 迭代抽象: 访问一个聚合对象的内容而无需暴露它的内部表示。 1. 迭代多态: 为遍历不同的集合结构提供一个统一的接口 ,从而支持同样的算法在不同的集合结构上进行操作。 1. 迭代器的健壮性考虑: 遍历的同时更改迭代器所在的集合结构,会导致问题。(并发修改异常)
微观代码
1. 提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以遍历对象了。 1. 隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚合的具体组成。 1. 提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任原则)。在聚合类中,我们把迭代器分开,就是要把维护对象底层数据结构和操作对象集合(如遍历)的责任分开,这样一来集合改变的话,只影响到聚合对象。而如果遍历方式改变的话,只影响到了迭代器。 1. 当要展示一组相似对象,或者遍历一组相同对象时使用, 适合使用迭代器模式 1. **缺点**: 每种(相同底层数据结构的)聚合对象都要一个(操作对应数据结构的)迭代器,会生成多个迭代器不好管理类
3.案例
需求
- 在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系。如图: -  - 其中. 每个 "学院" 中的 "专业"数据, 可能是不同的数据结构来存储
方案
- 将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小来进行分层次的
分析
- 实际上我们的要求是 :在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系, 因此这种方案,不能很好实现的遍历的操作 - 解决方案:=> 迭代器模式
4.使用模式
方案
- 使用迭代器模式, 使得具体的院校聚合一个(处理对应的数据结构的)具体的迭代器.
类图
- 
代码
5.经典使用
5.1JDK中ArrayList集合
分析
- 
类图
- 
说明
1. 内部类Itr 即 具体迭代器类, 只是依赖方式为: ArrayList 的内部类 1. List 充当了聚合接口,含有一个抽象的iterator():Iterator 方法--本质是其间接实现了 Iterable 接口 1. ArrayList 是实现聚合接口List的子类,实现了iterator() 1. 迭代器模式解决了不同集合(ArrayList ,LinkedList) 统一遍历问题
6.自定义List迭代器
说明
- [ArrayList及其迭代器](#puB6G)
类图
- 
代码
- 迭代器类: 操作数组的 / 操作链表的
/** * @description: 模拟ArrayList的(原内部类形式)迭代器. 本质是针对数组的迭代器 */public class MyArrayListIterator implements Iterator { // 底层数据 private Object[] elementData; // 当前下标 private int index = -1; // 构造器, 需要接受该迭代器对应类型的数据 public MyArrayListIterator(Object[] arr) { this.elementData = arr; } // Iterator接口中, 待实现的 hasNext(), next() // 在该类中, 是针对 数组 的操作实现 @Override public boolean hasNext() { if ( elementData[++index] != null ){ return true; } return false; } @Override public Object next() { return elementData[index]; }}/** * @description: 模拟LinkedList的迭代器. * 为方便测试, 底层直接用包装好的原生的LinkedList */public class MyLinkedListIterator implements Iterator { // 底层数据 List list; // 当前下标 int index = -1; // 构造器, 需要接受该迭代器对应类型的数据 public MyLinkedListIterator(List list){ this.list = list; } // Iterator接口中, 待实现的 hasNext(), next() // 在该类中, 是针对 链表 的操作实现 @Override public boolean hasNext() { if (index++ >= list.size()-1){ return false; } return true; } @Override public Object next() { return list.get(index); }}
- 简单的 自定义List 及自定义的 ArrayList/LinkedList 类
/** * @description: 自定义的抽象基类. 使得方便多态 */public abstract class MyList implements Iterable{ // 模拟List拥有的方法 protected abstract void add(Object object);}// 下面是具体的实现类/** * @description: 模拟 ArrayList. 其底层数据结构是数组 */public class MyArrayList extends MyList implements Iterable { Object[] elementData; // 底层数组 int size = 0; // 实际元素量 { // 设置默认容量, 不考虑扩容问题 this.elementData = new Object[512]; } // 简单的增加方法 @Override public void add(Object obj){ elementData[size++] = obj; } /** * @description: 返回该类对应的迭代器 */ @Override public Iterator iterator() { return new MyArrayListIterator(this.elementData); }}public class MyLinkedList extends MyList implements Iterable { // 方便起见, 直接使用jdk中包装了链表的LinkedList List list = new LinkedList(); // 简单的增加方法 @Override public void add(Object obj){ // 直接用LinkedList现有的, 方便测试 list.add(obj); } /** * @description: 返回该类对应的迭代器 */ @Override public Iterator iterator() { return new MyLinkedListIterator(this.list); }}
- 测试
public class Client { public static void main(String[] args) { MyArrayList myArrayList = new MyArrayList(); genericMethodForAddAndShow(myArrayList); System.out.println("-----------"); MyLinkedList myLinkedList = new MyLinkedList(); genericMethodForAddAndShow(myLinkedList); } /** * @description: 针对 MyList 的统一操作 * @param: list 传入的容器 */ public static void genericMethodForAddAndShow(MyList list){ { list.add("test1"); list.add("test2"); list.add("test3"); list.add("test4"); list.add("test5"); list.add("test6"); } // 通过不同的容器, 获取不同的迭代器. // 将 底层算法与容器 隔离.暴露一个共通效果(具体实现却不同)的接口 Iterator iterator = list.iterator(); System.out.println(iterator.getClass().getSimpleName()); while (iterator.hasNext()){ Object next = iterator.next(); System.out.println(next); } }}
MyArrayListIteratortest1test2test3test4test5test6-----------MyLinkedListIteratortest1test2test3test4test5test6