迭代器模式简述
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
迭代器模式属于行为型模式。
介绍
意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示,内部可以是数组或者链表等。
主要解决:不同的方式来遍历整个整合对象,实现迭代器接口的具有统一的遍历方式,而不用追究其本质。
何时使用:遍历一个聚合对象。
如何解决:把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码:定义接口:hasNext, next。
应用实例:JAVA 中的 iterator。C++ STL中的Iterator
优点:
- 它支持以不同的方式遍历一个聚合对象。
- 迭代器简化了聚合类。
- 在同一个聚合上可以有多个遍历。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点:
- 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类。
- 类的个数成对增加,这在一定程度上增加了系统的复杂性。
使用场景:
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 需要为聚合对象提供多种遍历方式。
- 为遍历不同的聚合结构提供一个统一的接口。
注意事项:迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
基本案例:
- 正向遍历迭代器实现(本文实现这个案例)
- 逆向遍历迭代器实现
迭代器设计模式划分:
- AggregateContainer 获取Iterator实例的接口定义
- ConcreteContainer实现AggregateContainer
- ConcreteIterator实现Iterator
- ConcreteIterator与ConcreteContainer配对,所以将ConcreteIterator作为ConcreteContainer的内部类
实现
场景:实现正向遍历迭代器
- 提供一种可以遍历对象集合的方式,又称为:游标cursor模式
- 聚合对象:存储数据,这里我在代码中定义成Container接口,用于获取迭代器对象
- 迭代器:遍历数据
步骤1:创建抽象了迭代器类,用于规划有哪些操作
package com.ly.iterator;
/**
* liyang 2020-08-21
* 自定义的迭代器接口
* 定义了一些常用的接口函数
*/
public interface MyIterator {
//迭代器初始值,如果有的地方需要,移动到-1位置,方便某些操作的统一性
void moveToMinusOne();
boolean moveToFirst(); //移动游标到第一个位置
boolean next(); //移动游标到下一个位置
boolean hasNext(); //判断游标是否有下一个位置
boolean isFirst(); //判断当前游标是否是第一个位置
boolean isLast(); //判断当前游标是否是最后一个位置
Object getCurrentObject(); //获取当前游标所指向的对象
}
步骤2:创建抽象的容器
package com.ly.iterator;
/**
* liyang 2020-08-21
* 抽象的聚合容器类,主要用于获取迭哪类代器
* 抽象的聚合容器被具体容器实现
*/
public interface AggregateContainer {
MyIterator getMyIterator();
}
步骤3:创建具体的容器类实现抽象的聚合容器类,由于迭代器的实现是为了对该具体容器的使用和操作,所以具体迭代器类在具体容器类中以内部类的方式存在,并且实现抽象迭代器接口
package com.ly.iterator;
import java.util.ArrayList;
import java.util.List;
/**
* liyang 2020-08-21
* 具体容器类实现抽象的聚合容器
* 具体的迭代器类实现抽象的迭代器,作为具体容器类的内部类
* 这里的具体的迭代器依托于list容器实现
* 上述get、set方法使用IDEA统一生成,有的可能在测试中未使用
*/
public class ConcreteContainer implements AggregateContainer {
private List<Object> list = new ArrayList<>();
public List<Object> getList() {
return list;
}
public void setList(List<Object> list) {
this.list = list;
}
void addObject(Object object) {
list.add(object);
}
void removeObject(Object object) {
list.remove(object);
}
@Override
public MyIterator getMyIterator() {
return new ConcreteIterator();
}
//使用内部类的定义方式,让ConcreteIterator服务于ConcreteContainer
private class ConcreteIterator implements MyIterator {
private int cursor = -1; //用于记录遍历时的位置
@Override
public void moveToMinusOne() {
cursor = -1;
}
@Override
public boolean moveToFirst() {
if(list.size() >= 1) {
cursor = 0;
return true;
}
return false;
}
@Override
public boolean next() {
if(hasNext()) {
cursor++;
return true;
}
return false;
}
@Override
public boolean hasNext() {
return cursor + 1 < list.size();
}
@Override
public boolean isFirst() {
return cursor == 0;
}
@Override
public boolean isLast() {
return cursor == list.size() - 1;
}
@Override
public Object getCurrentObject() {
if(cursor >= 0 && cursor < list.size()) return list.get(cursor);
else return null;
}
}
}
步骤4:客户端测试
package com.ly.iterator;
/**
* liyang 2020-08-21
* 客户端测试
*/
public class Client {
public static void main(String[] args) {
ConcreteContainer carNameContainer = new ConcreteContainer();
//测试添加
carNameContainer.addObject("byd");
carNameContainer.addObject("bmw");
carNameContainer.addObject("benz");
carNameContainer.addObject("audi");
//测试删除
carNameContainer.removeObject("bmw");
//获取迭代器,测试isFist()与isLast()
MyIterator myIterator = carNameContainer.getMyIterator();
System.out.println("Is first ? : " + myIterator.isFirst());
System.out.println("Move to first : " + myIterator.moveToFirst());
System.out.println("Is first now ? : " + myIterator.isFirst());
//遍历相关函数测试
System.out.println("--遍历方法1--");
if(myIterator.moveToFirst()) {
do {
System.out.println(myIterator.getCurrentObject());
} while(myIterator.next()); //next()内部先判断是否有next,即hasNext(),有则移动到下一个位置并返回真
}
System.out.println("Is last ? : " + myIterator.isLast());
System.out.println("--遍历方法2--");
if(myIterator.moveToFirst()) {
System.out.println(myIterator.getCurrentObject());
while(myIterator.next()) {
System.out.println(myIterator.getCurrentObject());
}
}
System.out.println("Is last ? : " + myIterator.isLast());
System.out.println("--遍历方法3--");
myIterator.moveToMinusOne();
while(myIterator.next()) {
System.out.println(myIterator.getCurrentObject());
}
System.out.println("Is last ? : " + myIterator.isLast());
}
}
结果
Is first ? : false
Move to first : true
Is first now ? : true
--遍历方法1--
byd
benz
audi
Is last ? : true
--遍历方法2--
byd
benz
audi
Is last ? : true
--遍历方法3--
byd
benz
audi
Is last ? : true
Process finished with exit code 0