基本概念
迭代器模式 iteratorpattern 属于行为设计模式,如果我们集合元素用不同的方式实现,有数组有集合或者其他的数据结构,当客户端要遍历元素的时候需要根据不同的数据结构使用不同的遍历方式,还会暴露对象内部存储的数据结构,这种时候可以考虑用迭代器模式。为外部提供一遍历集合元素的统一接口,使得客户端调用无需关心内部数据细节。
在java中有Iterator接口 实现他的3个方法即可
UML
角色分析
Iterator 迭代器顶级接口 JDK提供核心方法hasNext next remove
ConcreteIterator 具体的迭代器接口实现
Aggregate 聚合接口 用于返回一个迭代器对象 核心方法 createIterator 返回迭代器对象
ConcreteAggregate 具体聚合接口实现
Client 客户端调用 直接调用Aggregate 子类获取 Iterator 子类就可以实现对集合元素的遍历操作无需关系内部数据存储结构
代码示例
以一个学校院系结构为例,一个学校有多少学院,一个学院有多个系,一个系有多个部门,
其中学院,系,部门都是一个具体的迭代器对象ConcreteInerator
学院就是Aggregate 聚合了所有的结构
//顶级 Aggregate 抽象聚合接口 有添加和获取迭代器方法
public interface Collage {
void add(Dept dept);
Iterator createIterator();
}
// ConcreteIterator 具体实现迭代器的类 此处使用了List作为数据存取结构
public class ComputerCollageIterator implements Iterator<Dept> {
private final String name;
private List<Dept> depts;
private AtomicInteger index = new AtomicInteger(0);
private Integer size;
public ComputerCollageIterator(List<Dept> depts) {
this.name = "计算机";
this.depts = depts;
}
@Override
public boolean hasNext() {
return index.get() < depts.size();
}
@Override
public Dept next() {
if (this.hasNext()) {
return depts.get(index.getAndIncrement());
}
throw new NoSuchElementException();
}
// 因为调用remove 的时候已经调用了next将index往下移动了以为所有要删除元素需要将指针后移一位
@Override
public void remove() {
int position = index.decrementAndGet();
depts.remove(position);
}
public Integer getSize() {
return depts.size();
}
}
// 具体迭代器的实现类 此处使用了数组作为存储结构 其中hasNext Next remove 方法与List结构不同
public class MathCollageIterator implements Iterator<Dept> {
Dept[] depts;
private Integer size;
public MathCollageIterator(Dept[] depts) {
this.depts = depts;
}
private AtomicInteger index = new AtomicInteger(0);
@Override
public boolean hasNext() {
return index.get() < depts.length && depts[index.get()] != null;
}
@Override
public Dept next() {
if (hasNext()) {
return depts[index.getAndIncrement()];
}
throw new NoSuchElementException();
}
@Override
public void remove() {
Dept[] newDepts = new Dept[depts.length - 1];
index.decrementAndGet();
for (int i = 0; i < depts.length - 1; i++) {
if (index.get() <= i) {
newDepts[i] = depts[i + 1];
} else {
newDepts[i] = depts[i];
}
}
depts = newDepts;
}
public Integer getSize() {
return depts.length;
}
public String getDeptsStr() {
return Arrays.toString(depts);
}
}
// Concrete Aggregate具体的聚合实现类
public class ComputeCollageAggregate implements Collage {
List<Dept> depts;
public ComputeCollageAggregate() {
this.depts = new ArrayList<>();
depts.add(new Dept("计算机系部门1"));
depts.add(new Dept("计算机系部门2"));
depts.add(new Dept("计算机系部门3"));
depts.add(new Dept("计算机系部门4"));
}
// 根据结构不同添加方法略有不同
public void add(Dept dept) {
depts.add(dept);
}
public ComputerCollageIterator createIterator() {
return new ComputerCollageIterator(depts);
}
}
// concreteAggerate
public class MathCollageAggregate implements Collage {
Dept[] depts;
private AtomicInteger position = new AtomicInteger(0);
public MathCollageAggregate() {
this.depts = new Dept[10];
for (int i = 0; i < 5; i++) {
this.add(new Dept("数学系部门" + i));
}
}
public void add(Dept dept) {
depts[position.getAndIncrement()] = dept;
}
public MathCollageIterator createIterator() {
return new MathCollageIterator(depts);
}
}
// 客户端调用
public class IteratorTest {
public static void main(String[] args) {
ComputeCollageAggregate computeCollageAggregate = new ComputeCollageAggregate();
computeCollageAggregate.add(new Dept("新加的计算机部门"));
// 使用aggerate 获取iterator
ComputerCollageIterator computeIterator = computeCollageAggregate.createIterator();
System.out.println("初始元素"+computeCollageAggregate.getDepts());
System.out.println("删除之前集合数量: "+computeIterator.getSize());
while (computeIterator.hasNext()){
Dept next = computeIterator.next();
if(next.getName().equals("计算机系部门3")){
System.out.println("删除一个元素");
computeIterator.remove();
}else{
System.out.println(next);
}
}
System.out.println("删除之后集合数量: "+computeIterator.getSize());
System.out.println("删除之后集合"+computeCollageAggregate.getDepts());
System.out.println("===========================================");
MathCollageAggregate mathCollageAggregate = new MathCollageAggregate();
mathCollageAggregate.add(new Dept("新加的数学部门"));
// 使用aggerate 获取iterator
MathCollageIterator mathIterator = mathCollageAggregate.createIterator();
System.out.println("初始元素大小"+mathIterator.getSize());
System.out.println("初始元素"+mathIterator.getDeptsStr());
while (mathIterator.hasNext()){
Dept next = mathIterator.next();
if("数学系部门3".equals(next.getName())){
mathIterator.remove();
}else{
System.out.println(next);
}
}
System.out.println(" 删除元素大小"+mathIterator.getSize());
System.out.println("删除元素"+mathIterator.getDeptsStr());
}
}
使用细节
- 提供统一的遍历方法,客户端调用无需考虑具体聚合数据结构
- 隐藏内部聚合数据结构,客户端遍历只能得到迭代器对象
- 符合单一职责原则,将管理对象集合和遍历对象集合责任分开,管理对象集合实在Aggregate维护,遍历操作在Iterator中操作,集合改变只影响聚合对象,遍历方式改变只影响迭代器
- 每个对象都有一个迭代器增加管理难度