1.定义
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
简单来说:迭代器模式就是提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
2.概述
合理组织数据的结构以及相关操作是程序设计的一个重要方面,比如在程序设计中经常会使用诸如链表,散列表的等数据结构。链表和散列表等数据结构都是可以存放若干个对象的集合,其区别是按着不同的方式来存储对象。我们希望无论何种集合,应当允许程序以一种统一的方式遍历集合中的对象,而不需要知道这些对象在集合中是如何表示即存储的。
3.应用场景
1、访问一个聚合对象的内容而无须暴露它的内部表示。
2、需要为聚合对象提供多种遍历方式。
3、为遍历不同的聚合结构提供一个统一的接口。
4.模式的结构与使用
迭代器模式的结构中包括四种角色。
集合(Aggregate): 一个接口,规定了具体集合需实现的操作。
具体集合(ConcreteAggregate): 具体集合是实现集合接口类的实例,具体集合按照一定结构存储对象。具体集合应当有一个方法,该方法返回一个针对该集合的具体迭代器。
迭代器(Iterator): 一个接口,规定了遍历具体集合的方法,比如next()方法.
具体迭代器(ConcreteIterator): 实现了迭代器接口的类的实例。具体迭代器在实现迭代器接口所规定的遍历集合的方法时,比如next()方法,要保证next()方法的首次调用将按着集合的数据结构找到该集合中的一个对象,而且每当找到集合中的一个对象,立刻根据该集合的存储结构得到待遍历的后继对象的引用,并保证一次调用next()方法可以遍历集合。
1.迭代器模式的UML类图
2.结构的描述
以下通过一个简单的问题讲述迭代器模式中所涉及的各个角色。
用一种集合模拟保险箱,该集合用返回的迭代器模拟点钞机。
1.集合(Aggregate)
这里使用java.util包中的Collection接口作为模式中的集合角色。Java所有的单例集合都实现了该接口。
2.具体集合(ConcreteAggregate)
在这里使用java.util包中的ArrayList类的实例作为模式中的具体集合角色。
需要注意的是,在JDK1.5之后,要使用泛型,即使用ArrayList类(E是一个泛型)来创建一个集合对象。在使用ArrayList创建一个集合时,必须要指定E的具体类型,即指定集合中存放的对象的具体类型,例如:
Collection<RenMinMoney> set=new ArrayList<>();//定义集合对象
具体的集合继承关系如下图所示:
3.迭代器
在本问题中,使用的迭代器是java.util包中的Iterator接口,该接口有:
boolean hasNext();
Object next();
void remove();
三个方法。迭代通过调用next()方法依次返回集合中的对象,通过调用hasNext()方法判断集合中是否还有对象未被next()方法返回,调用remove()方法从集合中删除最近一次调用next()方法返回的对象。
4.具体迭代器
HashSet创建的集合可以使用iterator()方法返回一个实现Iterator接口类的实例,即一个具体的迭代器。
5.测试程序
package com.xing.Iterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Application {
public static void main(String[] args) {
int n=20;
int sum=0;
Collection<RenMinMoney> set=new ArrayList<>();//定义集合对象
for (int i = 1; i <=n; i++) {
if(i==n/2 || i==n/5 || i==n/6){
set.add(new RenMinMoney(100,false));//模拟定义假币
}else{
set.add(new RenMinMoney(100,true));
}
}
Iterator<RenMinMoney> iterator = set.iterator();//获得具体迭代器
System.out.println("保险箱共有"+set.size()+"张人民币");
int k=0;
while(iterator.hasNext()){
RenMinMoney money = iterator.next();
k++;
if(!money.isTrue()){
System.out.println("第"+k+"张是假币,已被销毁");
iterator.remove();
}
}
System.out.println("保险箱现有真人民币"+set.size()+"张,总价值是:");
iterator = set.iterator();
while (iterator.hasNext()){
RenMinMoney money = iterator.next();
sum+=money.getValue();
}
System.out.println(sum+"元");
}
}
class RenMinMoney{
int value;
private boolean isTrue;
public RenMinMoney(int value, boolean isTrue) {
this.value = value;
this.isTrue = isTrue;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isTrue() {
return isTrue;
}
public void setTrue(boolean aTrue) {
isTrue = aTrue;
}
}
6.测试结果展示
5.迭代器模式的优点
1.用户使用迭代器访问集合中的对象,而不需要知道这些对象在集合中是如何表示及存储的。
2.用户可以同时使用多个迭代器遍历一个结集合。