迭代器模式--导读
如果你已经开始看设计模式的话那么你一定对面想对象的容器有一定的了解,我们在开发的过程中一般都是用容器来存放大量的数据,而且我们在取数据的时候大多数时候都是用循环来进行取出存入的数据。但是容器有很多如list map,数组,等等,如果现在这有多种容器的话且我们需要对这些数据进行读取,毫无疑问我们需要些很多不同的循环去读取。这势必会很麻烦。下面举一个实例来进行说明。现有一个开发组,由于淘宝想跟京东进行合作,然后进行信息共享,但是数据库过于私密肯定不可能让对方进行直接访问,于是我们就需要在中间开发一个链接的桥梁对这两家进行信息交流,但是问题来了这两家存储信息的容器完全不一样,对信息的遍历的方式也完全不一样。所以我们需要创建两个循环在链接的过程中进行处理。代码如下:为了方便这里使用string来进行代表数据
JingDong,java用于模拟京东
package com.lwc.Iterator_Pattern; /** * 用于模拟京东对数据的进行传输 * @author Administrator * */ public class JingDong { //京东的数据存储是直接用数组进行存储的 //定义数组的初始化长度 private final int INFO_LENGTH=10; private String[] info; //获取数据的处理的日期 private String date; //数组的添加数据的大小 private int size; //数组的真实长度 private int length; public JingDong(int length ) { size=0; this.length=length; info=new String[length]; } public JingDong() { size=0; this.length=this.INFO_LENGTH; info=new String[this.length]; } public void addItem(String item) { if(size>length) System.out.println("数据已经满了"); else info[size++]=item; } public int getSize() { return size; } public String[] getInfo() { return info; } }
TaoBao.java 用于模拟淘宝公司
package com.lwc.Iterator_Pattern; import java.util.ArrayList; import java.util.List; /** * 模拟淘宝的数据存取 * @author Administrator * */ public class TaoBao { //淘宝数据用集合进行存储 private List<String> info; private String date; public TaoBao() { info=new ArrayList<String>(); } public void addItem(String item) { info.add(item); } public List<String> getInfo(){ return info; } }
中间对数据进行取出:
package com.lwc.Iterator_Pattern; public class test { public static void main(String[] args) { //通过另外一个循环读取京东中的数据 JingDong jingdong=new JingDong(); jingdong.addItem("项目1"); jingdong.addItem("项目2"); String[] str=jingdong.getInfo(); for(int i=0;i<jingdong.getSize();i++) System.out.println(str[i]); //通过循环读取淘宝中的数据 TaoBao taobao=new TaoBao(); taobao.addItem("项目3"); taobao.addItem("项目4"); for(String str2:taobao.getInfo()) System.out.println(str2); } }
从上面代码我们可以看出对于不同的数据集合其取出来的过程不相同,当我们有很多数据集合时要进行取出那么势必要很多循环进行取操作。为了改善这种情况,所以我们就想是不是可以来封装循环呢?不错就是封装遍历。这就是迭代器模式的动机--能够游走于聚合内的每一个元素,同时还可以提供多种不同的遍历方式。
迭代器模式--定义
何谓迭代器模式?所谓迭代器模式就是提供一种方法顺序访问一个聚合对象中的各个元素,而不是暴露其内部的表示。在实际的开发过程中,我们可能需要针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但是我们不希望在聚合对象的抽象接口层中充斥着各种不同的便利操作。这个时候我们就需要这样一种东西,它应该具备如下三个功能:
1、能够便利一个聚合对象。
2、我们不需要了解聚合对象的内部结构。
3、能够提供多种不同的遍历方式。
这三个功能就是迭代器模式需要解决的问题。作为一个功能强大的模式,迭代器模式把在元素之间游走的责任交给迭代器,而不是聚合对象。这样做就简化了聚合的接口和实现,也可以让聚合更专注在它所应该专注的事情上,这样做就更加符合单一责任原则。
迭代器模式--结构
迭代器模式UML类图:
从上面可以看书迭代器模式有如下几个角色:
Iterator: 抽象迭代器:所有迭代器都需要实现的接口,提供了游走聚合对象元素之间的方法。
ConcreteIterator: 具体迭代器。利用这个具体的迭代器能够对具体的聚合对象进行遍历。每一个聚合对象都应该对应一个具体的迭代器。
Aggregate: 抽象聚合类。
ConcreteAggregate: 具体聚合类。实现creatorIterator()方法,返回该聚合对象的迭代器。
迭代器模式--代码实现
下面对上述代码使用迭代器进行改良,类图如下:
以下是具体代码:
package com.lwc.Iterator_Pattern; /** * 定义迭代器的所有的父类接口 * @author Administrator * */ public interface Iterator<T> { public boolean hasNext(); public T next(); }
AggregateData.java
package com.lwc.Iterator_Pattern; /** * 所有聚合对象,抽像接口 * 定义了创建迭代器和一些聚合对象共有的方法 * @author Administrator * */ public interface AggregateData<T> { public Iterator<T> createIterator(); public void addData(T t); }
JingDongAggregate.java
package com.lwc.Iterator_Pattern; /** 由于泛型擦除,结果就是泛型的检查作用失效,可以将 List<Integer> 类型的值添加到 List<String>[] 类型的数组中。 而这类问题在编译时无法发现,只能在运行时出现问题 所以如果禁止创建泛型数组,就可以避免此类问题 所以该处直接采用object创建数组 * @author Administrator * */ public class JingDongAggregate implements AggregateData<Object>{ private final int MAX_SIZE=5; private Object[] objs; private int length; private int position=0; public JingDongAggregate(int length) { this.length=length; objs=new Object[length]; } public JingDongAggregate() { objs=new Object[this.MAX_SIZE]; length=this.MAX_SIZE; } @Override public Iterator<Object> createIterator() { return new JingDongIterator<Object>(objs,position); } @Override public void addData(Object t) { if(position<this.length) objs[position++]=t; else System.out.println("不好意思已经满了"); } }
JingDongIterator.java
package com.lwc.Iterator_Pattern; /** * 京东数据具体的迭代器 * * @author Administrator * @param <T> * */ public class JingDongIterator<T> implements Iterator<T> { //这里需要在迭代器中获取聚合类中的对象的一些属性,利用泛型可以更加广泛化 private T[] t; private int position; private int size; public JingDongIterator(T[] t ,int size) { this.size=size; position=0; this.t=t; } @Override public boolean hasNext() { return position<size?true:false; } @Override public T next() { return t[position++]; } }
TaoBaoAggregate.java
package com.lwc.Iterator_Pattern; import java.util.ArrayList; import java.util.List; /** * 具体的聚合类 * @author Administrator * * @param <T> */ public class TaoBaoAggregate<T> implements AggregateData<T>{ private List<T> lst; public TaoBaoAggregate() { lst=new ArrayList<T>(); } @Override public Iterator<T> createIterator() { return new TaoBaoIterator<T>(lst); } @Override public void addData(T t) { lst.add(t); } }
TaoBaoIterator.java
package com.lwc.Iterator_Pattern; import java.util.List; public class TaoBaoIterator<T> implements Iterator<T>{ private List<T> lst; private int position; public TaoBaoIterator(List<T> lst) { this.lst=lst; } @Override public boolean hasNext() { return position<lst.size()?true:false; } @Override public T next() { return lst.get(position++); } }
测试类:
package com.lwc.Iterator_Pattern; public class test { public static void main(String[] args) { /* * //通过另外一个循环读取京东中的数据 JingDong jingdong=new JingDong(); jingdong.addItem("项目1"); * jingdong.addItem("项目2"); String[] str=jingdong.getInfo(); for(int * i=0;i<jingdong.getSize();i++) System.out.println(str[i]); //通过循环读取淘宝中的数据 * TaoBao taobao=new TaoBao(); taobao.addItem("项目3"); taobao.addItem("项目4"); * for(String str2:taobao.getInfo()) System.out.println(str2); */ JingDongAggregate jda=new JingDongAggregate(); jda.addData("项目1"); jda.addData("项目2"); jda.addData("项目3"); Iterator<Object> it=jda.createIterator(); while(it.hasNext()) { System.out.println(it.next()); } TaoBaoAggregate<String> tba=new TaoBaoAggregate<String>(); tba.addData("项目1"); tba.addData("项目2"); tba.addData("项目3"); tba.addData("项目4"); Iterator<String> it2=tba.createIterator(); while(it2.hasNext()) { System.out.println("淘宝"+it2.next()); } } }
运行效果如下:
迭代器模式--优缺点
优点:
1、它支持以不同的方式遍历一个聚合对象。
2、迭代器简化了聚合类。
3、在同一个聚合上可以有多个遍历。
4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点:
由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
迭代器模式--使用场景
1、访问一个聚合对象的内容而无须暴露它的内部表示。
2、需要为聚合对象提供多种遍历方式。
3、为遍历不同的聚合结构提供一个统一的接口。
迭代器模式--总结
1、迭代器模式提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。
2、将遍历聚合对象中数据的行为提取出来,封装到一个迭代器中,通过专门的迭代器来遍历聚合对象的内部数据,这就是迭代器模式的本质。迭代器模式是“单一职责原则”的完美体现。
3、当使用迭代器的时候,我们依赖聚合提供遍历。
4、迭代器提供了一个通用的接口,让我们遍历聚合的项,放我们编码使用聚合项时,就可以使用多态机制。