一篇文章带你搞懂迭代器模式

迭代器模式

1、概要

  在面向对象编程中,迭代器模式是一种很常见的设计模式:它可以让用户透过特定的接口巡访容器中的每一个元素而不用了解底层的实现。就好像我们在使用集合的时候并不需要关注其底层实现是数组,链表或是其它数据结构,我们可以使用相同的方式去遍历集合中的元素而不暴露其内部结构,是不是感觉迭代器模式就是为了容器而生的!

  目的:迭代器模式提供了一种顺序遍历聚合对象元素而不用暴露其内部结构的方式

2、实现

在这里插入图片描述

  从类图可以看到迭代器的各个角色:主要是基于两个接口,然后通过其成对的实现类来实现,因此每一个具体容器对象都会聚合到关联的迭代器对象。具体类的功能如下:

  • Aggregate(抽象容器):是一个接口,具体容器都需要实现的接口,声明返回迭代器的方法
  • Iterator(抽象迭代器):是一个接口,具体迭代器都需要实现的接口,声明了迭代器的基本方法
  • ConcreteAggregate(具体容器):实现抽象容器的具体实现类,返回具体的迭代器对象
  • ConcreteIterator(具体迭代器):实现抽象迭代器的具体实现类,聚合了具体容器对象且根据其数据结构实现迭代逻辑

3 、示例

  • 定义容器抽象接口
package cn.blog.eight;

/**
 * @author lin
 * @version V1.0
 */
public interface MyCollection<T> {
    //定义集合大小
    public int size();

    //定义集合添加方法
    public boolean add(T t);

    //定义集合元素获取方法
    public T get(int i);

    //定义集合获取迭代器方法
    public MyIterator<T> iterator();
}

  定义了一个抽象容器MyCollection,用于规范容器的实现类。提供了操作集合基本方法如注释,且声明返回迭代器对象方法。

  • 定义迭代器抽象接口
package cn.blog.eight;

/**
 * @author lin
 * @version V1.0
 */
public interface MyIterator<T> {
    //获取当前游标前一位元素的值
    public T previous();

    //游标后移一位且获取当前游标的值
    public T next();

    //判断后一位元素是否存在
    public boolean hasNext();
}

  定义了一个抽象迭代器MyIterator。声明了迭代器的基本功能,功能如注释。

  • 具体容器实现
package cn.blog.eight;


import java.util.ArrayList;
import java.util.List;

/**
 * @author lin
 * @version V1.0
 */
public class MyList<T> implements MyCollection<T> {
    private final List<T> list = new ArrayList<>();

    @Override
    public int size() {
        return list.size();
    }

    @Override
    public boolean add(T t) {
        return list.add(t);
    }

    @Override
    public T get(int i) {
        return list.get(i);
    }

    @Override
    public MyIterator<T> iterator() {
        return new MyListIterator<>(this);
    }

    @Override
    public String toString() {
        return "MyList{" +
                "list=" + list +
                '}';
    }
}

  具体容器的实现类,可以看到底层实现是ArrayList,里面实现的增删查改方法也是从ArrayList偷过来的…

  • 具体迭代器实现
package cn.blog.eight;

import java.util.NoSuchElementException;

/**
 * @author lin
 * @version V1.0
 */
public class MyListIterator<T> implements MyIterator<T> {
    private final MyList<T> list;
    private int cursor = -1;

    public MyListIterator(MyList<T> list) {
        this.list = list;
    }

    @Override
    public T previous() {
        int i = cursor;
        if (cursor > 0) {
            return list.get(--i);
        } else {
            return (T) "为容器首项,没有前元素";
        }
    }

    @Override
    public T next() {
        if (cursor < list.size() - 1) {
            return list.get(++cursor);
        }
        throw new NoSuchElementException("集合越界!");
    }

    @Override
    public boolean hasNext() {
        return cursor < list.size() - 1;
    }
}

  实现了Iterator接口,聚合了MyList对象,完成了对其的遍历操作。

  • 测试
package cn.blog.eight;

/**
 * @author lin
 * @version V1.0
 */
public class Main {
    public static void main(String[] args) {
        MyCollection<String> coll = new MyList<>();
        coll.add("aa");
        coll.add("bb");
        coll.add("cc");
        coll.add("dd");
        MyIterator<String> it = coll.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println("当前元素:" + s);
            System.out.println(s + "元素前一个元素为:" + it.previous());
        }
        System.out.println(coll);
    }
}

  我们并不知道MyCollection的底层实现是如何的,但能直接使用迭代器对象对其进行遍历。因此我们后面有新的需求新增了成对的抽象容器实现类和抽象迭代器实现类,也可以使用此方式进行元素的遍历。其实Java集合中的迭代器模式和这个示例也是大同小异的,不同的集合对象底层的数据结构不同所以他们的迭代器实现逻辑也有一定的差异,但对于我们使用是无感的,具体实现可查看源码分析。

  • 结果
当前元素:aa
aa元素前一个元素为:为容器首项,没有前元素
当前元素:bb
bb元素前一个元素为:aa
当前元素:cc
cc元素前一个元素为:bb
当前元素:dd
dd元素前一个元素为:cc
MyList{list=[aa, bb, cc, dd]}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值