迭代子模式,又叫游标模式,该模式能顺序的访问一个聚集中的元素而不必暴露聚集的内部表象
-
上类图:
变化点:
- 在聚集系统的演化过程中,迭代逻辑没有变,但是需要将一种聚集换成另一种聚集。
- 聚集不会改变,但是聚集方式会改变
java中的集合分很多种,比如:ArrayList,LinkedList,TreeSet,HashSet等等这些就是我们说的不同聚集系统,不同的聚集有其不同的功能,如果我们不把通用的增删改查的操作抽象出来,那么每一种聚集(也就是每一个类)我们都得学习一下怎么用,就没有像现在只要学习一种其他的都一样,换一种聚集系统的时候,比如ArrayList换成LinkedList,而客户端的其他代码都不用修改这种效果了。
什么是主动迭代子和被动迭代子?
使用主动迭代子的客户端会显示的调用next等方法。
源码的 List,Set,Map 用了这个模式
-
代码示例:
- 定义抽象的
Iterator
接口,定义迭代子的行为
package com.byedbl.iterator;
/**
* Iterator Interface
*/
public interface Iterator {
void first();
void next();
boolean isDone();
void currentItem();
}
- 实现一个迭代子
package com.byedbl.iterator;
/**
* A vector iterator to print data reverse
*/
import java.util.*;
public class VectorIterator implements Iterator {
private Vector data = new Vector();
private int cursor = 0;
public VectorIterator(Vector _data) {
data = _data;
}
@Override
public void first() {
//cursor = 0;
cursor = (data.size() - 1);
}
@Override
public void next() {
//cursor++;
cursor--;
}
@Override
public boolean isDone() {
//return (cursor >= data.size());
return (cursor < 0);
}
@Override
public void currentItem() {
if(isDone()) {
System.out.println("Reach the end of the vector");
} else {
System.out.println("Number " + cursor + ": " + data.get(cursor));
}
}
}
- 定义聚集角色接口,给出创建迭代子的工厂方法
package com.byedbl.iterator;
/**
* The interface to create concrete iterator
* When create iterator, we can use Factory Method pattern
*/
public interface Aggregate {
Iterator createIterator();
}
- 实现一个聚集角色的接口
package com.byedbl.iterator;
/**
* Data stored in a vector
*/
import java.io.*;
import java.util.*;
import static org.springframework.util.ClassUtils.*;
public class DataVector implements Aggregate {
private Vector data = new Vector();
public DataVector(String fileName) {
try {
String absolutePath = getDefaultClassLoader().getResource(fileName).getFile();
BufferedReader f = new BufferedReader(new FileReader(absolutePath));
String s = f.readLine();
while (s != null) {
if (s.trim().length() > 0) {
data.add(s);
}
s = f.readLine();
}
f.close();
} catch (FileNotFoundException e) {
System.out.println("Can not find such file !");
} catch (IOException e) {
System.out.println("I/O Error !");
System.exit(0);
}
}
@Override
public Iterator createIterator() {
return new VectorIterator(data);
}
}
- 客户端用法
package com.byedbl.iterator; /**
*
*/
public class Test {
public static void main(String[] args) {
String fileName = "data.txt";
Aggregate dataVector = new DataVector(fileName);
Iterator iVector = dataVector.createIterator();
for(iVector.first(); ! iVector.isDone(); iVector.next()) {
iVector.currentItem();
}
}
}
好处:
- 遍历的算法被封装在迭代子角色里面,因此迭代的算法可以独立于聚集角色变化
- 客户端拿到的是一个迭代子对象,这样即使聚集对象发生变化也不用修改客户端遍历的代码
java中有个java.util.Iterator
类使用了迭代子模式,在java.util.AbstractList.Itr
内部类中实现了该接口,如果外界不是通过Iterator
接口的remove方法删除的话会报ConcurrentModificationException
异常
ListIterator
接口继承自java.util.Iterator
扩展了正向迭代和逆向迭代的功能,并提供了3个安全修改的方法,add(),remove(),set()
只有在调用了一次next或previous方法之后才能调用remove
,如果remove了之后还要调remove,必须先调用一次next或previous方法,set()
方法也有类似的逻辑
java.util.AbstractList.ListItr
实现了该接口