赞
踩
迭代器模式是我们学习一个设计时很少用到的、但编码实现时却经常使用到的行为型设计模式。在绝大多数编程语言中,迭代器已经成为一个基础的类库,直接用来遍历集合对象。在平时开发中,我们更多的是直接使用它,很少会从零去实现一个迭代器。
迭代器模式(Iterator pattern)又叫游标(Cursor)模式,它的原始定义是:迭代器提供一种对容器对象中的各个元素进行访问的方法,而又不需要暴露该对象的内部细节。
在软件系统中,容器对象拥有两个职责: 一是存储数据,而是遍历数据.从依赖性上看,前者是聚合对象的基本职责.而后者是可变化的,又是可分离的.因此可以将遍历数据的行为从容器中抽取出来,封装到迭代器对象中,由迭代器来提供遍历数据的行为,这将简化聚合对象的设计,更加符合单一职责原则
迭代器模式结构图
迭代器模式主要包含以下角色:
/** * 迭代器接口 **/ public interface Iterator<E> { //判断集合中是否有下一个元素 boolean hasNext(); //将游标后移一位元素 void next(); //返回当前游标指定的元素 E currentItem(); } /** * 具体迭代器 **/ public class ConcreteIterator<E> implements Iterator<E>{ private int cursor; //游标 private ArrayList<E> arrayList; //容器 public ConcreteIterator(ArrayList<E> arrayList) { this.cursor = 0; this.arrayList = arrayList; } @Override public boolean hasNext() { return cursor != arrayList.size(); } @Override public void next() { cursor++; } @Override public E currentItem() { if(cursor >= arrayList.size()){ throw new NoSuchElementException(); } return arrayList.get(cursor); } } public class Test01 { public static void main(String[] args) { ArrayList<String> names = new ArrayList<>(); names.add("lisi"); names.add("zhangsan"); names.add("wangwu"); Iterator<String> iterator = new ConcreteIterator(names); while(iterator.hasNext()){ System.out.println(iterator.currentItem()); iterator.next(); } /** * 使用ArrayList集合中的iterator()方法获取迭代器 * 将创建迭代器的方法放入集合容器中,这样做的好处是对客户端封装了迭代器的实现细节. */ java.util.Iterator<String> iterator1 = names.iterator(); while(iterator1.hasNext()){ System.out.println(iterator1.next()); iterator.next(); } } }
为了帮助你更好地理解迭代器模式,下面我们还是通过一个简单的例子给大家演示一下
/** * 抽象迭代器 IteratorIterator **/ public interface IteratorIterator<E> { void reset(); //重置为第一个元素 E next(); //获取下一个元素 E currentItem(); //检索当前元素 boolean hasNext(); //判断是否还有下一个元素存在 } /** * 抽象集合 ListList **/ public interface ListList<E> { //获取迭代器对象的抽象方法(面向接口编程) IteratorIterator<E> Iterator(); } /** * 主题类 **/ public class Topic { private String name; public Topic(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } /** * 具体迭代器 **/ public class TopicIterator implements IteratorIterator<Topic> { //Topic数组 private Topic[] topics; //记录存储位置 private int position; public TopicIterator(Topic[] topics) { this.topics = topics; position = 0; } @Override public void reset() { position = 0; } @Override public Topic next() { return topics[position++]; } @Override public Topic currentItem() { return topics[position]; } @Override public boolean hasNext() { if(position >= topics.length){ return false; } return true; } } /** * 具体集合类 **/ public class TopicList implements ListList<Topic> { private Topic[] topics; public TopicList(Topic[] topics) { this.topics = topics; } @Override public IteratorIterator<Topic> Iterator() { return new TopicIterator(topics); } } public class Client { public static void main(String[] args) { Topic[] topics = new Topic[4]; topics[0] = new Topic("topic1"); topics[1] = new Topic("topic2"); topics[2] = new Topic("topic3"); topics[3] = new Topic("topic4"); TopicList topicList = new TopicList(topics); IteratorIterator<Topic> iterator = topicList.Iterator(); while(iterator.hasNext()){ Topic t = iterator.next(); System.out.println(t.getName()); } } }
减少程序中重复的遍历代码
对于放入一个集合容器中的多个对象来说,访问必然涉及遍历算法。如果我们不将遍历算法封装到容器里(比如,List、Set、Map 等),那么就需要使用容器的人自行去实现遍历算法,这样容易造成很多重复的循环和条件判断语句出现,不利于代码的复用和扩展,同时还会暴露不同容器的内部结构。而使用迭代器模式是将遍历算法作为容器对象自身的一种“属性方法”来使用,能够有效地避免写很多重复的代码,同时又不会暴露内部结构。
当需要为遍历不同的集合结构提供一个统一的接口时或者当访问一个集合对象的内容而无须暴露其内部细节的表示时。
迭代器模式把对不同集合类的访问逻辑抽象出来,这样在不用暴露集合内部结构的情况下,可以隐藏不同集合遍历需要使用的算法,同时还能够对外提供更为简便的访问算法接口。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。