迭代器模式Iterator
迭代器模式提供一种方法顺序访问一个集合对象中的各个元素,而又不暴露其内部的表示。
一、为什么需要迭代器?
迭代器模式算是一个比较古老的设计模式,其源于对容器的访问,比如 Java 的 List 、Map 、数组等。
对容器对象的访问必然会设计遍历算法,可以将遍历的方法封装在容器中,或者不提供遍历方法。
如果将遍历的方法封装到容器中,那么对于容器类来说就承担了过多的功能,容器类不仅仅要维护自身内部的数据元素而且还要对外提供遍历的接口方法,因为遍历状态的存储问题还不能对同一个容器同时进行多个遍历操作。如果不提供遍历方法而让使用者自己去实现,又会让容器内部细节暴露无遗。
正因于此,迭代模式应运而生,在客户访问类与容器体之间插入了一个第三者 - 迭代器,很好地解决了上面所述的弊端。
总结起来,优点有:
- 可以不了解集合内部的数据结构,就可以直接遍历
- 不暴露内部的数据,可以直接外部遍历;
- 作为标准遍历,适用所有集合的遍历
二、代码实现
public interface Iterator<T> {
/**
* 是否还有下一个元素
* @return true 表示有,false 表示没有
*/
boolean hasNext();
/**
* 返回当前位置的元素并将位置移动到下一位
* @return
*/
T next();
}
public class ConcreteIterator<T> implements Iterator<T> {
/**
* 模拟用一个 List
*/
private List<T> mList = new ArrayList<>();
private int cursor = 0;
public ConcreteIterator(List<T> list) {
this.mList = list;
}
@Override
public boolean hasNext() {
return cursor != mList.size();
}
@Override
public T next() {
//定义一个临时变量
T obj = null;
if (this.hasNext()) {
obj = this.mList.get(cursor++);
}
return obj;
}
}
public interface Aggregate<T> {
/**
* 添加一个对象
* @param t
*/
void add(T t);
/**
* 删除的对象
* @param t
*/
void remove(T t);
/**
* 获取容器的迭代器
* @return
*/
Iterator<T> iterator();
}
public class ConcreteAggregate<T> implements Aggregate<T>{
/**
* 模拟具体容器
*/
private List<T> mLists = new ArrayList<>();
@Override
public void add(T t) {
mLists.add(t);
}
@Override
public void remove(T t) {
mLists.remove(t);
}
@Override
public Iterator<T> iterator() {
return new ConcreteIterator<T>(mLists);
}
}
@Test
public void testIterators() {
//创建容器
Aggregate<String> aggregate = new ConcreteAggregate<>();
aggregate.add("1");
aggregate.add("2");
aggregate.add("3");
aggregate.add("4");
//拿到容器迭代器,使用迭代器遍历
Iterator<String> iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println("Aggregate: " + iterator.next());
}
}
Aggregate: 1
Aggregate: 2
Aggregate: 3
Aggregate: 4
三、使用
对于迭代器模式来说,其自身优点很明显也很单一,支持以不同的方式去遍历一个容器对象,也可以有多个遍历,弱化了容器类与遍历算法之间的关系,其缺点就是对类文件的增加。
大家也可能会想到其他语言,如 C++、Python 、PHP 等,他们内部也有众多容器体的定义,当然,也有相应的迭代器。迭代器模式发展至今,几乎每一种高级语言都有相应的内置实现,对于开发者而言,已经极少会去自己实现迭代器了,因此,对于迭代器模式在于了解而非应用。