我们都知道,在计算机中,内存本质上是可以理解为一种类似抽屉的东西,在内存中放置一组集合对象,就有两种的方式:一种是连续放置,在java和c等编程语言中就是数组,这种放置方式放置和获取元素都比较方便,直接用下表就可以,但是扩容比较麻烦;另一种就是随便放,在每一个元素中记录下一个的内存地址,在java中就是链表的方式,这种方式天然支持良好的扩展性,但是随机访问就比较麻烦。而且在链表的基础上,为了取存更加的方便,后面还设计出了二叉树等各种数据结构,在不同的数据结构上,访问集合中的各种元素其实是依赖于数据结构本身的,使用起来就比较麻烦。为了向普通使用者屏蔽这种具体的结构,迭代器模式就应用而生了。迭代器提供了一种统一访问内部元素的方式,每种集合只要实现迭代器的接口,客户端就可以统一的访问内部元素,而不需要感知里面的具体实现。
在java语言中,已经内置实现了迭代器,而且我们能用到的集合基本上实现了迭代器的功能,所以我们平时只是用轮子,并不需要我们再去造轮子。为了学习迭代器模式,我们这里可以简单实现一个迭代器的功能,供大家参考学习。
自己实现一个迭代器
实现迭代器其实有两个维度:一个是迭代器本身的接口,提供了统一访问其中的元素的方法;另一个维度是集合的维度,要在集合中根据集合本身的元素,创建一个迭代器,然后客户端才能使用迭代器。具体代码如下:
1. 创建一个迭代器的接口,并写一个具体的实现类
/**
* 迭代器模式接口
*/
public interface Iterator<E> {
/**
* 判断是否含有下一个元素
*
* @return :
*/
boolean hasNext();
/**
* 获取下一个元素
*
* @return :
*/
E next();
}
/**
* 迭代器的具体实现类
*/
public class ConcreteIterator<E> implements Iterator<E> {
/**
* 持有一个对象的集合
*/
private final List<E> list;
/**
* 保存当前的index
*/
private int index = 0;
public ConcreteIterator(Collection<E> collection) {
list = new ArrayList<>(collection == null ? 0 : collection.size());
if (collection != null || collection.size() > 0) {
list.addAll(collection);
}
}
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public E next() {
return list.get(index++);
}
}
2. 创建一个集合的接口,并写一个具体的集合实现类,在实现类中,我们就内部直接用java的list来模拟内部的存储
/**
* 集合的接口
*/
public interface Aggregate<E> {
/**
* 添加
*
* @param e :
* @return :
*/
boolean add(E e);
/**
* 删除
*
* @param e :
* @return :
*/
boolean remove(E e);
/**
* 创建迭代器
*
* @return :
*/
Iterator<E> createIterator();
}
/**
* 集合的具体实现
*
* @param <E>
*/
public class ConcreteAggregate<E> implements Aggregate<E> {
private final List<E> list = new ArrayList<>();
@Override
public boolean add(E e) {
return list.add(e);
}
@Override
public boolean remove(E e) {
return list.remove(e);
}
@Override
public Iterator<E> createIterator() {
return new ConcreteIterator<>(this.list);
}
}
3. 编写一个测试类
public class Client {
@Test
public void testIterator() {
//创建并初始化集合
Aggregate<String> aggregate = new ConcreteAggregate<>();
aggregate.add("111");
aggregate.add("222");
aggregate.add("333");
aggregate.add("444");
aggregate.add("555");
aggregate.add("666");
aggregate.add("777");
//用迭代器方式访问
Iterator<String> iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
测试结果如下:
111
222
333
444
555
666
777
4. 类图如下
迭代器模式的思考
- java等高级语言中已经基本上都实现了迭代器的功能,我们并不需要重新造轮子,只需要知道怎么用和理解迭代器的思想即可
- 在实际的开发中,我们有很多地方还是能够用到迭代器的思路的,比如需要分页获取一大堆数据的时候,我们就可以利用迭代器的思想,在获取的对象中实现hasNext()和next()方法,统一的迭代获取数据,将具体的实现封装在获取的对象中。
- 设计模式是一种思维方式,平时看着用不上的东西,并不代表我们不需要学,往往在后续的功能开发中,就会用到其思想,给我们提供一种新的思路。
后记
个人总结,欢迎转载、评论、批评指正