遍历集合用的,不暴露集合的内部表示,但又能顺序访问内部的元素
- 定义:提供一种方法,顺序访问一个集合对象中的各个元素,而又不暴露该对象的内部表示
- 类型:行为型
- 适用场景:
- 访问一个集合对象的内容而无需暴露它的内部表示
- 为遍历不同的集合结构提供一个统一的接口
- 优点:分离了集合对象的遍历行为
- 缺点:类的个数成对增加
- 相关的设计模式:
- 迭代器模式和访问者模式:都是迭代的访问集合对象中的元素,不同的是,在访问者模式当中扩展开放的部分作用于对象的操作上,而迭代器模式中扩展开放的部分是在集合对象的种类上,这两者的实现方式有很大的区别
coding
/** * <p>抽象出来一个聚集类 == 提供创建集合对象迭代器的一系列抽象方法</p> * */ public abstract class AbstractAggregate { /** * <p>创建聚集对象的迭代器 == 使用迭代器对集合进行相关操作</p> * * @return 对象的迭代器 */ public abstract IIterator createIterator(); /** * <p>返回聚集对象(集合、迭代器对象)包含的对象(元素)的大小</p> * * @return 大小 */ public abstract int size(); /** * <p>聚集对象包含的元素是否为空</p> * * @return 空(true)不空(false) */ public abstract boolean isEmpty(); } /** * <p>自定义集合类,实现聚集抽象类中的迭代器的创建方法</p> * */ public class MyCollection extends AbstractAggregate { /** * 集合的底层用的就是数组 */ Object[] objArr; public MyCollection(Object[] objArr) { this.objArr = objArr; } @Override public IIterator createIterator() { /** * 将当前集合对象作为参数,调用迭代器的构造函数 * 注意,该方法的NB之处,就是同一个聚集对象可以new出来好多个迭代器 * 虽然,上面一段话说出来跟没说一样,但是博主还是想傻傻的强调一下 */ return new MyIterator(this); } @Override public int size() throws NullPointerException { if (objArr == null) { throw new NullPointerException("objArr is null !"); } return objArr.length; } @Override public boolean isEmpty() throws NullPointerException { if (objArr == null) { throw new NullPointerException("objArr is null !"); } return objArr.length == 0; } public Object[] getObjArr() { return objArr; } public void setObjArr(Object[] objArr) { this.objArr = objArr; } } /** * <p>迭代器接口</p> * */ public interface IIterator { /** * <p>当前迭代器中是否还有元素</p> * * @return 有(true) 没有(false) */ boolean hasNext(); /** * <p>取出迭代器中的元素</p> * * @return 对象 */ Object next(); /** * <p>取出迭代器中的第一个元素</p> * * @return 第一个元素 */ Object first(); } /** * <p>自定义迭代器,实现迭代器接口中的所有方法</p> * */ public class MyIterator implements IIterator { /** * 迭代器的目标对象,就是集合 */ private MyCollection collection; /** * 这里保留一份集合对象包含的元素的大小 */ private int size; /** * 记录元素的位置 */ private int pos = 0; public MyIterator(MyCollection collection) { this.collection = collection; this.size = collection.size(); } @Override public boolean hasNext() { /** * (1)只要size不等于pos初始化时候的0,集合里肯定是有元素的 * (2)返回true的时候,一定不要忘了让pos往后移,这就是迭代器只能使用一次的原因所在 * (3)如果想复用迭代器,调用first函数,重置pos位置的值 */ if (pos < size) { pos++; return true; } return false; } @Override public Object next() { return collection.getObjArr()[pos - 1]; } @Override public Object first() { pos = 0; return collection.getObjArr()[0]; } }
UML
测试
/** * <p>迭代子模式测试 == 典型的类似集合的方式实现了我们自己的迭代器,通过迭代器实现元素的遍历</p> * */ public class IteratorTest { public static void main(String[] args) { myIterator(); } private static void myIterator() { Integer[] numArr = new Integer[]{1, 2, 3}; AbstractAggregate aggregate = new MyCollection(numArr); IIterator iterator = aggregate.createIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("==============若想要迭代器继续迭代输出元素"); System.out.println("first = " + iterator.first()); System.out.println("==============我们可以调用first方法重置pos"); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println("==============我们再来创建一个迭代器对象出来"); IIterator iteratorOther = aggregate.createIterator(); while (iteratorOther.hasNext()) { System.out.println(iteratorOther.next()); } } /** * <p>描述迭代子模式:</p> * 迭代子模式又叫游标模式,是对象的行为模式。 * 迭代子模式可以顺序的访问一个聚集中的元素而不必暴露聚集内部表象。 * * 优点: * (1)本来聚集类要干的事情,分担给具体的迭代器类了,聚集类和迭代器实现了很好的解耦, * 这样一来,迭代的算法可以完全独立于聚集类; * (2)一个聚集类的对象,也就是聚集对象,可以创建出N个迭代器,同时进行元素迭代而互不干扰 */ } =========输出结果========= 1 2 3 ==============若想要迭代器继续迭代输出元素 first = 1 ==============我们可以调用first方法重置pos 1 2 3 ==============我们再来创建一个迭代器对象出来 1 2 3
源码中的应用
- java.util.Iterator:可以看它里面的方法