2.1、设计模式 [行为型]- 迭代器模式(Iterator Pattern)

原创
2022/06/09 08:50
阅读数 110

迭代器模式

迭代器模式(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一般就能满足我们的需求!

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部