likes
comments
collection
share

设计模式-迭代器模式

作者站长头像
站长
· 阅读数 45

# 七大软件设计原则 # 设计模式-工厂模式 # 设计模式-单例模式 # 设计模式-原型模式 # 设计模式-策略模式 # 设计模式-责任链模式 # 设计模式-建造者模式 # 设计模式-深度分析代理模式 # 设计模式-门面模式 # 设计模式-装饰器模式 # 设计模式-享元模式 # 设计模式-组合模式 # 设计模式-适配器模式 # 设计模式-桥接模式 # 设计模式-委派模式 # 设计模式-模板方法模式

迭代器模式 (Iterator Pattern)又称为游标模式(Cursor Pattern),它提供一种顺序访问集合/ 容器对象元素的方法,而又无须暴露集合内部表示(到底是列表、栈还是树等)。迭代器模式可以为不同的容器提供一致的 遍历行为,而不用关心容器内容元素组成结构,属于行为型模式。

迭代器模式UML类图

设计模式-迭代器模式 实现代码如下(这里使用的集合是list,也可以使用其他集合这里就不一一展示了)

public interface Iterator<T> {
    T next();
    boolean hasNext();
}
public class ConcreteIterator<T> implements Iterator<T>{
    private final List<T> list;
    private int cursor = 0;

    public ConcreteIterator(List<T> list){
        this.list = list;
    }

    @Override
    public T next() {
        if(hasNext()) {
            return list.get(cursor++);
        }
        return null;
    }

    @Override
    public boolean hasNext() {
        return list.size() > cursor;
    }
}
public interface IAggregate {
    void add(User user);
    void remove(User user);

    Iterator<User> iterator();
}
public class ConcreteAggregate implements IAggregate{
    private final List<User> users = new ArrayList<>();

    @Override
    public void add(User user) {
        users.add(user);
    }

    @Override
    public void remove(User user) {
        users.remove(user);
    }

    @Override
    public Iterator<User> iterator() {
        return new ConcreteIterator<>(users);
    }
}
public class Test {
    public static void main(String[] args) {
        User user1 = new User("张三", "123");
        User user2 = new User("张三2", "123");
        User user3 = new User("张三3", "123");
        User user4 = new User("张三4", "123");
        User user5 = new User("张三5", "123");
        User user6 = new User("张三6", "123");
        User user7 = new User("张三7", "123");
        ConcreteAggregate concreteAggregate = new ConcreteAggregate();
        concreteAggregate.add(user1);
        concreteAggregate.add(user2);
        concreteAggregate.add(user3);
        concreteAggregate.add(user4);
        concreteAggregate.add(user5);
        concreteAggregate.add(user6);
        concreteAggregate.add(user7);
        Iterator<User> iterator = concreteAggregate.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().toString());
        }
    }
}

设计模式-迭代器模式 看完这些代码后可能有些人会说直接for循环不是很简单,的确很多时候for循环的确很简单,但是遇到上文中的删除操作那你的for循环是不是会有点问题,当然还有人说这个问题很好解决。当你遇到的集合是树、图再用for循环是不是很复杂,而且你的业务中有很多这样的结构的时候你的for循环是不是到处都是,如果我们写一个迭代器,复杂遍历逻辑放到迭代器里面使用到的地方只需要调用岂不是很方便,代码也相对更优雅一些

迭代器在源码中的应用

我们知道java中的集合最终都会实现Iterable接口如下图所示: 设计模式-迭代器模式 我们可以看一下Iterable源码

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());
    }
}

发现和上文中定义的几乎一样 这里我们可以看一下迭代器的具体实现(这里拿List举例) 设计模式-迭代器模式 发现具体实现类是 ListItr再看源码:

private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public E previous() {
        checkForComodification();
        try {
            int i = cursor - 1;
            E previous = get(i);
            lastRet = cursor = i;
            return previous;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException(e);
        }
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor-1;
    }

    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            AbstractList.this.set(lastRet, e);
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            AbstractList.this.add(i, e);
            lastRet = -1;
            cursor = i + 1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

这里面就实现了List的遍历

迭代器模式的优缺点

优点:

  1. 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的集合对象
  2. 简化集合对象接口:迭代器模式将集合对象本身应该提供的元索迭代接口抽取到了迭代器 中,使集合对象无须关心具体迭代行为
  3. 元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使的同种元素聚 合结构可以有不同的迭代行为;
  4. 解耦迭代与集合:迭代器模式封装了具体的迭代算法,迭代算法的变化,不会影响到集合 对象的架构

缺点: 对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐。

正常情况下我们在写项目的时候很少会用到迭代器模式,常用集合底层都帮我们实现了迭代器,所以我们用就可以了。一般情况下我们都是在使用轮子而非造轮子

转载自:https://juejin.cn/post/7176559285319499837
评论
请登录