定义
提供一种方法顺序地访问一个集合对象中各个元素,而又不需要暴露该对象的内部表示。
对于一个集合来说,它应该有提供一种方法让外界可以对它进行遍历,同时根据不同的需求也需要支持多种遍历方式。由于不能预知所有的遍历需求,所以不可能在集合中写出所有的遍历逻辑(即使能预知所有的需求,也不应该在集合中写出所有的遍历方式)。
迭代器模式可以解决这个问题,其关键思想是:将集合的遍历与集合本身分离,并将遍历逻辑封装成单独的迭代器对象,根据不同的需求定义不同的迭代器对象,从而达到不同的遍历逻辑。
任务
对于一个迭代器对象来说,它至少需要具备以下功能:
1,对集合进行遍历时跟踪当前元素,即:它必须知道哪些元素已经被遍历过了。
2,迭代器的健壮性。在遍历迭代器的同时更改这个聚合可能是危险的,一个健壮的迭代器必须保证插入和删除元素时不会干扰遍历——在不采用拷贝原集合的情况下。
关键字
遍历——对集合中各个元素进行遍历。
内部迭代器与外部迭代器
定义好迭代器后,遍历的推进是由哪一方控制。如果由客户端控制时就是外部迭代器,由迭代器自身控制时就是内部迭代器。
使用外部迭代器时,客户端必须主动地推进迭代步伐,显式地向迭代器请求下一个元素——java中常用的ArrayList的迭代器属于此类。
使用内部迭代器时,客户端只需要提交一个待执行的操作,迭代器将对集合中每一个元素实施该操作——此举类似于python中filter,map,reduce等操作。
内部迭代器的示例如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//入口
List<String> ss = new ArrayList<>();
ss.add("xx1");
ss.add("xx2");
ss.add("xx3");
inner(ss.iterator(), new Operate<String>() {
@Override
public void o(String s) {
Log.e("TAG",s);
}
});
}
private <T>void inner(Iterator<T> iterator,Operate<T> operate){
while (iterator.hasNext()){
operate.o(iterator.next());
}
}
private interface Operate<T>{
void o(T t );
}
对于一个内部迭代器,传递进了一个操作对象,然后传递进了一个迭代器,由inner()方法进行迭代并对每一个元素进行操作——完全不需要外部调用迭代器。这完全类似于python中的filter,map等函数的实现。
外部迭代器比较灵活。例如要比较两个集合中的元素是否一样,用外部迭代器很容易实现,而使用内部迭代器基本上不可能实现。
内部迭代器比较简单,因为所有的迭代逻辑已经定义在了迭代器内容。
空迭代器
对一个不需要遍历的集合定义一个空迭代器,有助于处理边界条件。空迭代器总是已经完成了遍历。
相关模式
工厂方法
不同的集合会使用不同的迭代器对象,因此不能在集合的总父类中简简单单地实例化一个具体的迭代器对象,必须将迭代器的实例化延迟到子类中执行——这就是工厂方法模式。
迭代器模式会产生两个类层次——一个是迭代器的、一个是集合的,而工厂方法是联系这两个类层次的钮带。