设计模式之迭代器模式
定义
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需暴露该对象的内部表示。如我们日常生活中的快递,不管内部是什么物品,
都会被统一打包,我们不需要关心里面是什么,只需要按照目的地发送即可。
结构
- Iterator,迭代器接口,定义访问和遍历元素的方法。
- ConcreteIterator,具体迭代器实现对象,实现对聚合对象的遍历。
- Aggregate,聚合对象接口,定义创建迭代器对象的方法。
- ConcreteAggregate,具体聚合对象,实现创建相应的迭代器对象。
简单实现
迭代器接口
public interface Iterator {
boolean hasNext();
Object next();
}
具体迭代器
public class ConcreteIterator implements Iterator {
private ConcreteAggreate aggreate;
private int cursor = 0;
public ConcreteIterator(ConcreteAggreate aggreate) {
this.aggreate = aggreate;
}
@Override
public boolean hasNext() {
return cursor < aggreate.size();
}
@Override
public Object next() {
return aggreate.get(cursor++);
}
}
聚合对象接口
public interface Aggregate {
Iterator createIterator();
}
具体聚合对象的实现
public class ConcreteAggreate implements Aggregate {
private String[] data;
public ConcreteAggreate(String[] data) {
this.data = data;
}
public int size() {
return data.length;
}
public String get(int index) {
if (index < 0 || index >= data.length) {
return null;
}
return data[index];
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
}
客户端
public class Client {
public static void main(String[] args) {
ConcreteAggreate aggreate = new ConcreteAggreate(new String[]{"a","b","c"});
Iterator iterator = aggreate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
输出为
a
b
c
java中已经提供了 Iterator 接口和 Iterable 接口来实现迭代器模式。
import java.util.Iterator;
public class ConcreteIterator implements Iterator {
private ConcreteAggreate aggreate;
private int cursor = 0;
public ConcreteIterator(ConcreteAggreate aggreate) {
this.aggreate = aggreate;
}
@Override
public boolean hasNext() {
return cursor < aggreate.size();
}
@Override
public Object next() {
return aggreate.get(cursor++);
}
}
具体聚合对象
public class ConcreteAggreate implements Iterable {
private String[] data;
public ConcreteAggreate(String[] data) {
this.data = data;
}
public int size() {
return data.length;
}
public String get(int index) {
if (index < 0 || index >= data.length) {
return null;
}
return data[index];
}
@Override
public java.util.Iterator iterator() {
return new ConcreteIterator(this);
}
}
客户端
import java.util.Iterator;
public class Client {
public static void main(String[] args) {
ConcreteAggreate aggreate = new ConcreteAggreate(new String[]{"a", "b", "c"});
Iterator iterator = aggreate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
迭代器模式在JDK的实现
JDK中ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
// prevent creating a synthetic constructor
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
}
}
JDK中的ArrayList,LinkedList,HashSet等都实现了迭代器模式。
总结
优点
- 更好的封装性,访问一个聚合对象的内容而无需暴露该聚合对象的内部表示。
- 支持以不同的方式来遍历聚合对象。
缺点
- 增加新的聚合类需要增加对应的迭代器类。
本质
迭代器模式的本质是控制访问聚合对象中的元素。
使用场景
- 当我们想访问一个聚合对象的内容而又不想暴露内部表示时,可以使用迭代器模式,实际开发中我们一般使用java自身提供的迭代器实现。
参考
大战设计模式【12】—— 迭代器模式
设计模式的征途—21.迭代器(Iterator)模式
设计模式(十七)——迭代器模式(ArrayList 集合应用源码分析)
迭代器模式(详解版)
研磨设计模式-书籍