迭代器模式

28 阅读2分钟

定义

提供一种可以顺序访问一个聚合对象中的各种元素的方法,同时又不暴露该对象的内部表示。

目的

遍历一个对象

优点

访问一个聚合数据,聚合数据不会暴露内部内容

缺点

会增加类的个数,增加系统复杂性

解释

在我们开发的过程中,经常要访问一个聚合对象中的各个元素,比如链表的遍历。我们在遍历链表时,通常是将链表的创建和遍历都放在同一个类中,但这种方式不利于程序的扩展,如果要更换遍历方法就必须修改程序源代码,这显然是违背了 “开闭原则”;

如果类中不提供遍历方法,直接将遍历方法由客户端自己实现是否可行呢?答案也是否定的,因为这样做会带来两个弊端:

  • 暴露了聚合类的内部表示,使其数据不安全;
  • 给客户端带来了麻烦。增加了负担;

所以为了解决这种情况,我们就需要用到迭代器模式了。它在客户端访问类与聚合类之间插入了一个迭代器,就可以将聚合对象与其遍历行为进行分离,同时也对客户端访问类隐藏了其内部细节,且满足“单一职责原则”和“开闭原则”,就像 Java 中的 Collection、List 等等都是迭代器模式的良好体现;

迭代器模式所包含的几个角色:
抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

实例

//迭代接口
public interface Iterator {
    boolean hasNext();
    Object next();
}
//容器接口
public interface Container{
    Iterator getIterator();
}
//容器
public class NameContainer implements Container {

    public String[] names = {"name1" , "name2" ,"name3" , "name4"};

    @Override
    public Iterator getIterator() {
        return new NameIterator();
    }

    class NameIterator implements Iterator{

        int index;

        @Override
        public boolean hasNext() {
            if(index < names.length){
                return true;
            }
            return false;
        }

        @Override
        public Object next() {
            if(this.hasNext()){
                return names[index++];
            }
            return null;
        }
    }
}
//使用
NameContainer nameContainer = new NameContainer();
Iterator it = nameContainer.getIterator();
while(it.hasNext()){
    String name = (String) it.next();
    System.out.println(name);
}

Iterator接口,必须实现下一个 对象 和 是否有下一个对象。Container接口 需要返回一个实现Iterator接口的类。
在java中HashMap的内部类KeySet有Iterator,android中访问数据库有Cursor,都是是用了迭代器模式