设计模式
本系列文章均是博主原创,意在记录学习上的知识,同时一起分享学习心得。提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
本章一起学习迭代器模式的原理、使用方式和适用场景。
一、原理
迭代器是用来遍历容器对象的,所以一个完整的迭代器模式一般会涉及容器和容器迭代器两部分内容。为了达到基于接口而非实现编程的目的,容器又包括容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。
二、实现方式
迭代器的代码实现方式如下:
- 定义一个迭代器接口,并实现一个迭代器类。
- 定义一个容器接口,并实现一个容器类。
1、迭代器
先定义一个迭代器接口,迭代器接口有两种定义方式:
- 第一种,包含3个方法。
方法名 | 描述 |
---|---|
next() | 用来将游标后移一位 |
currentItem() | 返回当前游标指向的元素 |
hasNext() | 判断是否还有下一个元素 |
- 第二种,包含2个方法。
方法名 | 描述 |
---|---|
next() | 当前游标指向的元素,并将游标后移一位 |
hasNext() | 判断是否还有下一个元素 |
第一种方式更加灵活一些,比如我们可以多次调用currentItem()查询当前元素,而不移动游标。
但是JDK的迭代器Iterator接口就是用的第二种方式,本示例代码也采用第二种。
代码如下(示例):
public class MyIterator implements Iterator {
int cursor;
List list;
public MyIterator(List list) {
this.cursor = 0;
this.list = list;
}
@Override
public boolean hasNext() {
return cursor < list.size();
}
@Override
public Object next() {
int i = cursor;
if (i >= list.size()) {
throw new RuntimeException();
}
cursor++;
return list.get(i);
}
}
2、容器
定义一个接口,其中该接口包含一个方法:
方法名 | 描述 |
---|---|
iterator() | 该方法返回一个迭代器类 |
代码如下(示例):
public class MyIterator implements Iterator {
int cursor;
List list;
public MyIterator(List list) {
this.cursor = 0;
this.list = list;
}
@Override
public boolean hasNext() {
return cursor < list.size();
}
@Override
public Object next() {
int i = cursor;
if (i >= list.size()) {
throw new RuntimeException();
}
cursor++;
return list.get(i);
}
}
测试代码:
@Test
public void testIterator() {
MyList<String> list = new MyList<>();
Iterator<String> iterator = list.iterator();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
总结
利用迭代器来遍历有下面三个优势:
- 迭代器模式封装集合内部的复杂数据结构,开发者不需要了解如何遍历,直接使用容器提供的迭代器即可;
- 迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一;
- 迭代器模式让添加新的遍历算法更加容易,更符合开闭原则。除此之外,因为迭代器都实现自相同的接口,在开发中,基于接口而非实现编程,替换迭代器也变得更加容易。