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);
}
}
}
MyArrayListIterator
test1
test2
test3
test4
test5
test6
-----------
MyLinkedListIterator
test1
test2
test3
test4
test5
test6