迭代器模式是一种行为型设计模式,它提供了一种遍历集合元素的统一接口,使得在不暴露集合内部结构的情况下可以顺序访问其中的每个元素。迭代器模式具有以下特点:
- 提供一种遍历集合元素的统一接口。
- 隐藏集合内部结构,客户端不需要关心集合的具体实现。
- 可以同时遍历多个集合,只要它们提供相同的迭代器接口。
迭代器模式的主要角色有:
- 迭代器(Iterator):定义遍历集合元素的接口,包括获取下一个元素、判断是否有下一个元素等方法。
- 具体迭代器(Concrete Iterator):实现迭代器接口,负责遍历集合的具体实现。
- 集合(Aggregate):定义创建迭代器的接口,即返回一个迭代器对象。
- 具体集合(Concrete Aggregate):实现集合接口,返回一个具体迭代器对象。
下面是一个使用 Java 实现的迭代器模式的例子:
java
// 迭代器接口
interface Iterator {
boolean hasNext();
Object next();
}
// 具体迭代器
class ConcreteIterator implements Iterator {
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
}
@Override
public boolean hasNext() {
return current< aggregate.size();
}
@Override
public Object next() {
if (hasNext()) {
return aggregate.getElement(current++);
}
return null;
}
}
// 集合接口
interface Aggregate {
Iterator iterator();
}
// 具体集合
class ConcreteAggregate implements Aggregate {
private Object[] elements;
private int size = 0;
public ConcreteAggregate(int size) {
this.elements = new Object[size];
}
public void add(Object element) {
if (size< elements.length) {
elements[size++] = element;
}
}
public Object getElement(int index) {
return elements[index];
}
public int size() {
return size;
}
@Override
public Iterator iterator() {
return new ConcreteIterator(this);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
ConcreteAggregate aggregate = new ConcreteAggregate(5);
aggregate.add("A");
aggregate.add("B");
aggregate.add("C");
aggregate.add("D");
aggregate.add("E");
Iterator iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
在这个例子中,我们定义了一个 ConcreteAggregate
类,它实现了 Aggregate
接口,并提供了一个 iterator()
方法来返回一个 ConcreteIterator
对象。ConcreteIterator
类实现了 Iterator
接口,并在其内部维护了一个指向 ConcreteAggregate
对象的引用,用于遍历集合中的元素。客户端可以通过调用 iterator()
方法获取迭代器对象,并使用迭代器的 hasNext()
和 next()
方法遍历集合中的元素。
迭代器模式的优点:
- 遍历集合元素时,不需要关心集合的内部结构,只需要关心迭代器的接口。
- 可以同时遍历多个集合,只要它们提供相同的迭代器接口。
- 可以在遍历过程中,对集合进行修改,而不会影响遍历的正确性。
迭代器模式的缺点:
- 需要为每个集合类提供一个具体的迭代器类,增加了代码的复杂性。
- 迭代器模式不支持并发访问,如果多个线程同时遍历同一个集合,可能会出现数据不一致的问题。
场景举例
场景一:遍历集合
迭代器模式是一种非常有用的设计模式,它提供了一种在不暴露集合内部结构的情况下,顺序访问集合中元素的方法。在实际开发中,我们经常需要遍历各种类型的集合,如数组、列表、栈、队列等。使用迭代器模式可以使代码更加简洁、灵活和可维护。
以遍历一个整数数组为例,我们可以使用迭代器模式来实现:
java
public interface Iterator<T> {
boolean hasNext();
T next();
}
public class ArrayIterator<T> implements Iterator<T> {
private T[] array;
private int index;
public ArrayIterator(T[] array) {
this.array = array;
index = 0;
}
@Override
public boolean hasNext() {
return index< array.length;
}
@Override
public T next() {
return array[index++];
}
}
public class Array<T> {
private T[] array;
public Array(T[] array) {
this.array = array;
}
public Iterator<T> iterator() {
return new ArrayIterator<>(array);
}
}
public class IteratorPatternDemo {
public static void main(String[] args) {
Integer[] numbers = {1, 2, 3, 4, 5};
Array<Integer> integerArray = new Array<>(numbers);
Iterator<Integer> iterator = integerArray.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
}
在这个例子中,我们定义了一个通用的迭代器接口 Iterator
,它包含两个方法:hasNext()
和 next()
。然后,我们为整数数组实现了一个具体的迭代器类 ArrayIterator
,它实现了 Iterator
接口。最后,我们创建了一个 Array
类,它包含一个数组,并提供了一个 iterator()
方法,用于返回一个迭代器对象。
场景二:数据库查询
在数据库查询中,我们经常需要遍历查询结果集。使用迭代器模式可以使代码更加简洁、灵活和可维护。
以JDBC为例,我们可以使用迭代器模式来实现对数据库表的查询操作:
java
public interface ResultSetIterator<T> extends Iterator<T> {
void close();
}
public class ResultSetIteratorImpl<T> implements ResultSetIterator<T> {
private ResultSet resultSet;
private Class<T> entityClass;
public ResultSetIteratorImpl(ResultSet resultSet, Class<T> entityClass) {
this.resultSet = resultSet;
this.entityClass = entityClass;
}
@Override
public boolean hasNext() {
try {
return resultSet.next();
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
@Override
public T next() {
try {
T entity = entityClass.newInstance();
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String columnName = field.getName();
Object value = resultSet.getObject(columnName);
field.set(entity, value);
}
return entity;
} catch (InstantiationException | IllegalAccessException | SQLException e) {
e.printStackTrace();
return null;
}
}
@Override
public void close() {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class DatabaseAccessor {
private Connection connection;
public DatabaseAccessor(String url, String username, String password) {
try {
connection = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
}
public <T> Iterator<T> query(String sql, Class<T> entityClass) {
try {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet resultSet = preparedStatement.executeQuery();
return new ResultSetIteratorImpl<>(resultSet, entityClass);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
public void close() {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public class IteratorPatternDemo {
public static void main(String[] args) {
DatabaseAccessor databaseAccessor = new DatabaseAccessor("jdbc:mysql://localhost:3306/test", "root", "password");
String sql = "SELECT * FROM users";
Iterator<User> iterator = databaseAccessor.query(sql, User.class);
while (iterator.hasNext()) {
User user = iterator.next();
System.out.println(user);
}
databaseAccessor.close();
}
}
在这个例子中,我们定义了一个通用的带关闭方法的迭代器接口 ResultSetIterator
,它继承自 Iterator
接口。然后,我们为JDBC查询结果集实现了一个具体的迭代器类 ResultSetIteratorImpl
,它实现了 ResultSetIterator
接口。最后,我们创建了一个 DatabaseAccessor
类,它包含了连接数据库和查询数据的方法,并提供了一个 query()
方法,用于返回一个迭代器对象。在 main()
方法中,我们演示了如何使用 DatabaseAccessor
类查询数据库表,并使用迭代器遍历查询结果集。