迭代器模式

151 阅读3分钟

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。

对于设计模式,我们都知道,是为了方便软件开发,让代码看起来更加规整,开发起来更有效率,从而总结的“经验”。

接下来的系列我们将会使用Java 语言,开始讲解一些常用的设计模式,带大家了解对应的设计规范。

迭代器模式

什么是迭代

可能有的人看到迭代两个字感觉比较难理解。迭代本身的含义是:更相替代;轮换。

对应到实际的Java 开发中,迭代的意思最常见的使用场景就是for循环。

Java 中的迭代器其实就是用一个游标,不断地指向下一个对象,每次处理一个对象,这样就不用把集合中的元素一下都塞到内存中处理。

迭代器模式

迭代器模式的目的就是让用户通过特定的接口访问容器(集合)的数据,不需要了解其内部的数据结构。

我们都知道,Java 里面有迭代接口Iterator,为什么我们还要再去设计一个迭代器呢?

因为Java 里面的迭代器不允许改变容器(集合)的内容。

举例:

public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        // 为list 添加元素
        for (int i = 0; i < 5; i++) {
            list.add(i);
        }
        // 获取迭代器
        Iterator<Integer> it = list.iterator();
        // 遍历元素
        while(it.hasNext()) {
            if(it.next().equals(3)) {
                list.remove(it.next());
            }
        }
    }
}

有兴趣的同学可以实际试一下,运行上述代码会报错。再一步证实了我们不能在迭代元素的时候进行增删改的操作。

同时还有另外一个重要的原因,就是我们在迭代元素的时候,是会有可能会去修改集合容器中的元素,而这种操作会带来极大的不安全。因为你不知道用户访问这个数据要执行什么操作。

于是,迭代器模式出现了,能为我们很好的解决上面的两个问题。

迭代器模式包含4 个角色:

(1)Aggregate集合:创建迭代子的接口;

(2)ConcreteAggregate 具体集合:实现迭代子接口;

(3)Iterator 迭代子接口:给出迭代每个元素的接口;

(4)ConcreteIterator 具体迭代子:实现迭代方法。

接下来我们用代码举例讲解一下:

第一步:定义抽象容器

public abstract class Aggregate {
    // 定义迭代器
    public abstract MyIterator iterator(); 
    public abstract Object getElement(int index);
    public abstract int size();
}

第二步:定义ConcreteAggregate 具体集合容器

public class ConcreteAggregate extends Aggregate{
    private List<String> list=new ArrayList<>(); 
    public ConcreteAggregate() {
        list.add("元素1");
        list.add("元素2");
        list.add("元素3");
        list.add("元素4");
    }
    @Override
    public MyIterator iterator() {
        return new ConcreteIterator(this);
    } 
    public Object getElement(int index){
        return list.get(index);
    }
    public int size(){
        return list.size();
    }
}

第三步:Iterator 迭代子接口

public interface MyIterator {
    //移动到第一个对象
    public void first();
    //是否最后
    public boolean isLast();
    //移动下一个
    public void next();
    //当前对象
    public Object current();
}

第四步:ConcreteIterator 具体迭代子

public class ConcreteIterator implements MyIterator{
    Aggregate agg;
    int size=0;
    int index=0;    
    public ConcreteIterator(Aggregate agg) {
        this.agg=agg;
        size=agg.size();
    }    
    @Override
    public void first() {
        index=0;   
    }
    @Override
    public boolean isLast() {
        return index>=size;
    }
    @Override
    public void next() {
        if(index<size){
            index++;
        }    
    }
    @Override
    public Object current() {
        return agg.getElement(index);
    }
}

最后我们在客户端调用一下

public class Test {
    public static void main(String[] args) {
        Aggregate agg=new ConcreteAggregate();
        MyIterator iterator = agg.iterator();
        while(!iterator.isLast()){
            System.out.println(iterator.current());
            iterator.next();
        }
    }
}

其实,在我们日常开发中,迭代器模式是使用的比较少的一个设计模式。这里我们就理解一下它的思想就好了。文章开始说的java 自带的迭代器的缺点,其实换一下用法就可以避免了,这里我们就不在赘述了。希望读者可以自行查明。