一 定义
提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
迭代器模式属于行为型模式。
迭代器(Iterator)模式,又叫做游标(Cursor)模式。
Java中的Map、List等等容器,都使用到了迭代器模式。
二 UML类图
- Iterator(迭代器接口):负责定义、访问和遍历元素的接口。
- ConcreteIterator(具体迭代器类):实现迭代器接口。
- Aggregate(容器接口):定义容器的基本功能以及提供创建迭代器的接口。
- ConcreteAggregate(具体容器类):实现容器接口中的功能。
- Client(客户端类):即要使用迭代器模式的地方。
三 代码实现
3.1 创建迭代器接口
interface Iterator {
fun hasNext(): Boolean //是否存在下一条记录
fun next(): Any? //返回当前记录并移到下一条记录
}
3.2 创建容器接口
定义容器的基本功能以及提供创建迭代器的接口:
interface Aggregate {
fun size(): Int //容器大小
fun get(location: Int): String? //获取获取中指定位置的号码
fun add(tel: String?) //添加号码到容器中
fun remove(tel: String?) //从容器中移除号码
fun iterator(): Iterator? //返回容器的迭代器
}
3.3 创建具体迭代器类
实现迭代器接口:
class MyIterator() : Iterator {
private var aggregate : Aggregate? = null //容器对象:
private var index = 0 //当前索引
constructor(aggregate: Aggregate?) : this(){
this.aggregate = aggregate
}
override operator fun hasNext(): Boolean { //是否存在下一条记录
if (index < aggregate!!.size()) {
return true
} else {
return false
}
}
override fun next(): Any? { //返回当前记录并移到下一条记录
return aggregate!!.get(index++)
}
}
3.4 创建具体容器类
实现容器接口中的功能:
class MyAggregate : Aggregate {
var list :ArrayList<String?> = ArrayList<String?>()
override fun size(): Int {
return list.size
}
override fun get(location: Int): String? {
return list.get(location)
}
override fun add(tel: String?) {
list.add(tel)
}
override fun remove(tel: String?) {
list.remove(tel)
}
override fun iterator(): Iterator? {
return MyIterator(this)
}
}
3.5 客户端测试
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val aggregate: Aggregate = MyAggregate()
aggregate.add("1111")
aggregate.add("2222")
aggregate.add("3333")
aggregate.add("4444")
val iterator: Iterator? = aggregate.iterator()
while (iterator!!.hasNext()) {
val tel = iterator!!.next() as String
Log.d(TAG,"当前号码为:$tel")
}
println()
Log.d(TAG,"后面没有了")
}
四 应用场景
遍历一个容器对象时。实际我们开发中很少使用到迭代器模式。虽然不怎么用得到,但是了解其原理能够让我们在看到相关的源码(如Java中的Map、List等等容器)时能够更容易了解源码的相关思想。
五 优缺点
优点:
- 可以支持以不同的方式去遍历容器对象,如顺序遍历,逆序遍历等等。
- 符合单一职责原则,容器类与遍历算法的分离,不同类负责不同的功能。
缺点:
- 会产生多余的对象,消耗内存。
- 会增多类文件。
- 遍历过程是一个单向且不可逆的遍历。
- 遍历过程需要注意容器是否改变,若期间改变了,可能会抛出异常。
六 Android中的源码分析
除了Java中的Map、List等有用到迭代器模式之外,Android中使用数据库查询时返回的Cursor游标对象,实际上就是使用了迭代器模式来实现,首先先让我们来看下怎么使用Cursor:
8.1 使用Cursor
Cursor cursor = sqLiteDatabase.query("table", null, null, null, null, null, null);//各种参数请自行查询用法,这里就不说明了
if (cursor.moveToFirst()) {//游标指向第一行
do {
cursor.getInt(0);//获得第一列数据
cursor.getString(1);//获得第二列数据
} while (cursor.moveToNext());//移到下一行
}
8.2 Cursor源码
//Cursor是一个接口,实际上就是迭代器接口
public interface Cursor extends Closeable {
//其他代码略
boolean moveToFirst();
int getInt(int columnIndex);
String getString(int columnIndex);
boolean moveToNext();
}