迭代器模式的结构:
抽象容器:一般是一个接口,提供一个得到迭代器(iterator)的方法,例如java中的Collection接口,List接口,Set接口等。
具体容器:就是抽象容器的具体实现类,比如List接口的有序列表实现ArrayList,List接口的链表实现LinkList,Set接口的哈希列表的实现HashSet等。
抽象迭代器:定义遍历元素所需要的方法,一般来说会有这么三个方法:取得第一个元素的方法first(),取得下一个元素的方法next(),判断是否遍历结束的方法isDone()(或者叫hasNext()),移出当前对象的方法remove()。
迭代器实现:实现迭代器接口中定义的方法,完成集合的迭代。
1.容器接口Container :里面定义了容器的基本功能,比如添加对象,计算容器内对象数量,还提供一个得到迭代器的方法getIterator()。
public interface Container {
void add(Object o);
int size();
Iterator getIterator();
}
2.抽象迭代器Iterator:定义了遍历容器时需要用到的基本方法。
public interface Iterator {
Object next();
boolean hasNext();
}
3.具体容器(ContainerOne和ContainerTwo)和迭代器实现(IteratorOne和IteratorTwo),这里将迭代器的具体实现放在内部类里面以方便实现。
public class ContainerOne implements Container {
Object[] objects = new Object[10];
int index = 0;
public void add(Object o) {
if (index == objects.length) {
Object[] newObjects = new Object[objects.length * 2];
System.arraycopy(objects, 0, newObjects, 0, objects.length);
objects = newObjects;
}
objects[index] = o;
index++;
}
public int size() {
return index;
}
//迭代器具体实现放在了内部类里面
private class IteratorOne implements Iterator {
private int x = 0;
public boolean hasNext() {
if (x >= index) {
return false;
} else {
return true;
}
}
public Object next() {
Object o = objects[x];
x++;
return o;
}
}
@Override
public Iterator getIterator() {
return new IteratorOne();
}
}
public class ContainerTwo implements Container {
Node head = null;
Node tail = null;
int size = 0;
public void add(Object o) {
Node n = new Node(o, null);
if (head == null) {
head = n;
tail = n;
}
tail.setNext(n);
tail = n;
size++;
}
public int size() {
return size;
}
public Iterator getIterator() {
return new IteratorTwo();
}
private class IteratorTwo implements Iterator {
private Node node = head;
public boolean hasNext() {
if (head.getNext() == null) {
return false;
} else {
return true;
}
}
public Object next() {
Object o = node.getDate();
node = node.getNext();
return o;
}
}
}
从上面代码可以看出容器ContainerOne 的底层是数组,默认容量设置为10,随着存储对象增加而增加为原来的两倍。这有点像ArrayList。
ContainerTwo的底层是链表,有点像LinkedList 。由于存储的方式不同,遍历的过程也大不相同,分别于自己的迭代器。
存储对象Cat
public class Cat {
private int id;
public Cat(int id) {
super();
this.id = id;
}
@Override
public String toString() {
return "Cat [id=" + id + "]";
}
}
Test
public class Test {
public static void main(String[] args) {
Container con = new ContainerOne();
for (int i = 0; i < 15; i++) {
con.add(new Cat(i));
}
Iterator it = con.getIterator();
while (it.hasNext()) {
try {
Object o = it.next();
System.out.print(o + " ");
} catch (NullPointerException e) {
}
}
}
}
输出:
Cat [id=0] Cat [id=1] Cat [id=2] Cat [id=3] Cat [id=4] Cat [id=5] Cat [id=6] Cat [id=7] Cat [id=8] Cat [id=9] Cat [id=10] Cat [id=11] Cat [id=12] Cat [id=13] Cat [id=14]
客户程序要先得到具体容器角色,使用这个容器的添加移除等功能,不用知道具体的过程,然后再通过具体容器角色得到具体迭代器角色。然后使用迭代器的遍历功能,不用知道具体实现过程这。(正是所谓的针对接口编程)
迭代器模式优点:
1) 访问一个容器对象的内容而无需暴露它的内部表示。
2) 支持对容器对象的多种遍历。
3) 为遍历不同的容器结构提供一个统一的接口(多态迭代)。