迭代器模式
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
介绍
意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
主要解决: 不同的方式来遍历整个整合对象。
何时使用: 遍历一个聚合对象。
如何解决: 把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码: 定义接口:hasNext, next。
应用实例: JAVA 中的 iterator。
优点:
1、它支持以不同的方式遍历一个聚合对象。
2、迭代器简化了聚合类。
3、在同一个聚合上可以有多个遍历。
4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点:
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
使用场景:
1、访问一个聚合对象的内容而无须暴露它的内部表示。
2、需要为聚合对象提供多种遍历方式。
3、为遍历不同的聚合结构提供一个统一的接口。
注意事项:
迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
实现
迭代器模式角色:
Iterator抽象迭代器:抽象迭代器负责定义访问和遍历元素的接口,而且基本上是有固定3个方法:first()获得第一个元素,next()访问下一个元素,isDon()是否已经访问到底部(Java叫做hasNext()方法)。
ConcreteIterator具体迭代器:具体迭代器角色要实现迭代器接口,完成容器元素的变量。
Aggregate抽象容器:容器角色负责提供创建具体迭代器角色的接口,必须提供一个类似createIterator()这样的方法,在Java中一般是iterator()方法。
Concrete Aggregate具体容器:具体容器实现容器接口定义的方法,创建出容纳迭代器的对象。
抽象迭代器
public interface Iterator {
public Object next();
public boolean hasNext();
public boolean remove();
}
具体迭代器
public class ConcreteIterator implements Iterator{
private Vector vector=new Vector();
public int cursor=0;
public ConcreteIterator(Vector vector) {
this.vector = vector;
}
@Override
public Object next() {
Object result=null;
if(this.hasNext()){
result=this.vector.get(this.cursor++);
}
return result;
}
@Override
public boolean hasNext() {
if(this.cursor==this.vector.size()){
return false;
}
return true;
}
@Override
public boolean remove() {
this.vector.remove(this.cursor);
return true;
}
}
抽象容器
public interface Aggregate {
public void add(Object object);
public void remove(Object object);
public Iterator iterator();
}
具体容器
public class ConcreteAggregate implements Aggregate {
private Vector vector=new Vector();
@Override
public void add(Object object) {
this.vector.add(object);
}
@Override
public void remove(Object object) {
this.remove(object);
}
@Override
public Iterator iterator() {
return new ConcreteIterator(this.vector);
}
}
场景类
public class Client {
public static void main(String[] args){
Aggregate agg=new ConcreteAggregate();
agg.add("123");
agg.add("456");
agg.add("789");
Iterator iterator=agg.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
JDK Iterable与Iterator接口分析
Iterable接口
Java集合最顶层接口。 JDK描述为:实现此接口允许对象成为“ for-each循环”语句的目标;实现该接口就可以使用foreach进行迭代.
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Iterator接口 迭代器接口,实现此接口的实例可以对元素集合进行迭代遍历。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
两者区别:
Iterator是迭代器接口,实现此接口的实例可以对元素集合进行迭代遍历。而实现Iterable接口就可以> 使用foreach进行迭代
Iterable中封装了Iterator接口,只要实现了Iterable接口的类,就可以使用Iterator迭代器了。JDK中集合Collection、List、Set都是Iterable的实现类。
Iterator.forEachRemaining() 方法内部是通过使用迭代器Iterator遍历所有元素,该方法二次调用不会做任何操作,因为不会有下一个元素了。而Iterable.forEach()方法内部使用的是增强for循环,此方法可多次调用
Iterator 中的方法都是依赖于当前位置,若集合实现Iterator则必须维护包括当前迭代位置的指针。Iterable则不然,每次返回的Iterator(迭代器对象)都是从头开始的,各个迭代器之前互不影响。
注意 由于JDK已经为我提供了集合,以及相关的迭代器功能;因此,我们基本不需要自己来实现。使用JDK提供的Iterator一般就能满足我们的需求!