【行为型模式七】迭代器模式
一、封装自定义数据结构的访问方式
通常我们可能会自定义一种数据结构,例如数组实现的栈,需要提供一个访问该栈中各个元素的方法,又不想暴露该栈是用数组实现的还是链表实现的。就可以使用迭代器模式。通常每种语言中都内置了迭代器模式,例如Java中的Iterable接口,就是为迭代器模式准备的。所有能使用foreach方式遍历的容器(所有Collection的子类)都实现了Iterable接口。
二、迭代器模式
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示,其别名为游标(Cursor)。迭代器模式是一种对象行为型模式。
迭代器模式就是分离了集合变量的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
2.1 迭代器模式的角色
使用迭代器模式实现数组栈遍历的类图:
-
Iterator(抽象迭代器):它定义了访问和遍历元素的接口,声明了用于遍历数据元素的方法,例如:用于获取第一个元素的first()方法,用于访问下一个元素的next()方法,用于判断是否还有下一个元素的hasNext()方法,用于获取当前元素的currentItem()方法等,在具体迭代器中将实现这些方法。
-
ConcreteIterator(具体迭代器):它实现了抽象迭代器接口,完成对聚合对象的遍历,同时在具体迭代器中通过游标来记录在聚合对象中所处的当前位置,在具体实现时,游标通常是一个表示位置的非负整数。
-
Aggregate(抽象聚合类):它用于存储和管理元素对象,声明一个createIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。
-
ConcreteAggregate(具体聚合类):它实现了在抽象聚合类中声明的createIterator()方法,该方法返回一个与该具体聚合类对应的具体迭代器ConcreteIterator实例。
三、使用迭代器模式实现数组栈遍历
3.1 抽象迭代器类
public abstract class Iterator {
public abstract boolean hasNext();
public abstract Object first() throws Exception;
public abstract Object next() throws Exception;
}
3.2 具体迭代器类
此类实现从栈顶到栈底遍历。
public class ConcreteIterator extends Iterator {
private ConcreteAggregate concreteAggregate;
private int cursor;
public ConcreteIterator(ConcreteAggregate concreteAggregate) {
this.concreteAggregate = concreteAggregate;
cursor = concreteAggregate.getSize();
}
@Override
public boolean hasNext() {
return cursor > 0;
}
@Override
public Object first() throws Exception {
cursor = concreteAggregate.getSize() - 1;
return concreteAggregate.current(cursor);
}
@Override
public Object next() throws Exception {
return concreteAggregate.current(--cursor);
}
}
3.3 抽象聚集类
只有一个创建迭代器的方法
public abstract class Aggregate {
public abstract Iterator createIterator();
}
3.4 具体聚集类
实现一个数组栈。
public class ConcreteAggregate extends Aggregate{
private Integer[] intStack;
private int capacity;
private int size = 0;
public int getCapacity() {
return capacity;
}
public int getSize() {
return size;
}
public ConcreteAggregate(int capacity) {
this.capacity = capacity;
intStack = new Integer[capacity];
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(this);
}
public void push(int num) throws Exception {
if (size < capacity) {
intStack[size++] = num;
}else {
throw new Exception("栈已满!");
}
}
public int pop() throws Exception {
if (size > 0) {
return intStack[--size];
}else {
throw new Exception("栈已空!");
}
}
public int current(int index) throws Exception {
if (size > 0 && index < size) {
return intStack[index];
}else if (size == 0){
throw new Exception("栈为空!");
}else {
throw new Exception("索引越界!");
}
}
}
3.5 客户端
public class Client {
/**
* 使用迭代器模式遍历数组栈
*/
public static void showByIterator() throws Exception {
ConcreteAggregate intStack = new ConcreteAggregate(5);
for (int i = 0; i < intStack.getCapacity(); i++) {
intStack.push(i);
}
Iterator stackIterator = intStack.createIterator();
while (stackIterator.hasNext()) {
System.out.println(stackIterator.next());
}
}
public static void main(String[] args) {
try {
showByIterator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 运行结果
4
3
2
1
0
实现从栈顶到栈底遍历了该栈。
四、迭代器模式总结
在迭代器模式中,提供了一个外部的迭代器来对聚合对象进行访问和遍历,迭代器定义了一个访问该聚合元素的接口,并且可以跟踪当前遍历的元素,了解哪些元素已经遍历过而哪些没有。迭代器的引入,将使得对一个复杂聚合对象的操作变得简单。
在迭代器模式中应用了工厂方法模式,抽象迭代器对应于抽象产品角色,具体迭代器对应于具体产品角色,抽象聚合类对应于抽象工厂角色,具体聚合类对应于具体工厂角色。