iterator(迭代器模式)

迭代器模式

   针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但我们不希望在集合容器的抽象接口层中充斥着各种不同的遍历操作,这
时候我们就需要一种能完成下面功能的迭代器:

	(1)遍历一个集合对象
	(2)不需要了解聚合对象的内部结构
	(3)提供多种不同的遍历方式

   迭代器模式提供一种访问集合中的各个元素,而不暴露其内部表示的方法。将在元素之间游走的职责交给迭代器,而不是集合对象,从而简化
集合容器的实现,让集合容器专注于在它所应该专注的事情上,更加符合单一职责原则。

UML结构图

在这里插入图片描述

  1. 迭代器角色(Iterator)提供了在集合容器元素之间游走的方法。
  2. 具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。
  3. 容器角色(Aggregate):抽象容器类,一般是一个接口,提供一个iterator()方法
  4. 具体容器角色(ConcreteAggregate):具体容器类,实现抽象容器类 ,返回该聚合对象的迭代器。

代码实现

抽象迭代器

	package com.lq.Iterator;
	
	/**
	 * @author lq
	 * @PACKAGE_NAME: com.lq.Iterator
	 * @CLASS_NAME: Iterator_
	 * @date 2022/11/9 21:41
	 * @Description:  迭代器角色(Iterator)提供了在集合容器元素之间游走的方法。
	 */
	public interface Iterator_<E> {
	
	    boolean hasNext();
	
	    E next();
	}

抽象容器类

	package com.lq.Iterator;
	
	/**
	 * @author lq
	 * @PACKAGE_NAME: com.lq.Iterator
	 * @CLASS_NAME: Collection_
	 * @date 2022/11/9 21:42
	 * @Description:  抽象容器类,一般是一个接口,提供一个iterator()方法
	 */
	public interface Collection_<E> {
	
	    void add(E o);
	
	    int size();
	
	    Iterator_ iterator();
	}

具体容器类(内部类-- 具体迭代器角色)

	package com.lq.Iterator;
	
	/**
	 * @author lq
	 * @PACKAGE_NAME: com.lq.Iterator
	 * @CLASS_NAME: ArrayList_
	 * @date 2022/11/9 21:42
	 * @Description:  具体容器类,实现抽象容器类 ,返回该聚合对象的迭代器。
	 */
	public class ArrayList_<E> implements Collection_<E> {
	
	    E[] objects = (E[])new Object[10];
	
	    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
	    private int index = 0;
	    @Override
	    public void add(E o) {
	        if(index == objects.length) {
	            E[] newObjects = (E[])new Object[objects.length*2];
	            System.arraycopy(objects, 0, newObjects, 0, objects.length);
	            objects = newObjects;
	        }
	
	        objects[index] = o;
	        index ++;
	    }
	
	    @Override
	    public int size() {
	        return index;
	    }
	
	    /**
	     *  调用内部类,好处:自己的迭代器只对自己开放,不能随便调用
	     */
	
	    @Override
	    public Iterator_<E> iterator() {
	        return new ArrayListIterator<>();
	    }
	
	    /**
	     * 具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。
	     * @param <E>
	     */
	    private class ArrayListIterator<E> implements Iterator_<E> {
	
	        private int currentIndex = 0;
	
	        @Override
	        public boolean hasNext() {
	            if(currentIndex >= index) {
	                return false;
	            }
	            return true;
	        }
	
	        @Override
	        public E next() {
	            E o = (E)objects[currentIndex];
	            currentIndex ++;
	            return o;
	        }
	    }
	}

测试

	package com.lq.Iterator;
	
	/**
	 * @author lq
	 * @PACKAGE_NAME: com.lq.Iterator
	 * @CLASS_NAME: Main
	 * @date 2022/11/9 21:42
	 * @Description:
	 */
	
	public class Main {
	    public static void main(String[] args) {
	        Collection_<String> list = new ArrayList_<>();
	        for (int i = 0; i < 15; i++) {
	            list.add("测试 :" + i);
	        }
	        System.out.println("长度 :" + list.size());
	
	        //这个接口的调用方式:
	        Iterator_<String> it = list.iterator();
	        while (it.hasNext()) {
	            String o = it.next();
	            System.out.println(o);
	        }
	    }
	}

结果

	长度 :15
	测试 :0
	测试 :1
	测试 :2
	测试 :3
	测试 :4
	测试 :5
	测试 :6
	测试 :7
	测试 :8
	测试 :9
	测试 :10
	测试 :11
	测试 :12
	测试 :13
	测试 :14

迭代器模式总结

优点:

  1. 迭代器模式简化了集合的接口,迭代子具备遍历功能,这样集合的接口就不需要重新实现遍历功能。
  2. 每一个聚集对象都可以有一个或多个迭代子对象,每一个迭代子的迭代状态可以是彼此独立的。因此,一个聚集对象可以同时有几个迭代在进行之中。
  3. 由于遍历算法被封装在迭代子角色里面,因此迭代的算法可以独立于聚集角色变化。
  4. 更好的封装性,访问一个集合对象的元素,无需暴露容器内部表示。

缺点:

  1. 迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  2. 对于比较简单的遍历,使用迭代器模式显得较为繁琐,比如ArrayList直接就可以用for循环+get() 方法来遍历;
  3. 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展,例如JDK内置迭代器Iterator就无法实现逆向遍历,如果需要实现逆向遍历,只能通过其子类ListIterator等来实现,而ListIterator迭代器无法用于操作Set类型的聚合对象。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是件很容易的事情。

适用场景:

  1. 访问一个集合对象的内容而无须暴露它的内部表示。
  2. 需要为集合对象提供多种遍历方式。
  3. 为遍历不同的聚合结构提供一个统一的接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值