迭代器模式 (Iterator Pattern)
概述
迭代器模式是一种行为型设计模式,它提供了一种方法来访问一个容器对象中的各个元素,而又不暴露该对象的内部表示。迭代器模式将遍历逻辑从集合类中分离出来,使集合类更加专注于数据的存储和管理。
迭代器模式的核心思想是提供一个统一的接口,用于遍历不同类型的集合对象,而不需要关心集合对象的具体实现细节。这样,客户端代码就可以使用相同的方式遍历不同类型的集合。
核心要点
- 提供统一的遍历接口:通过迭代器接口,客户端可以以相同的方式遍历不同的集合
- 封装遍历逻辑:将集合的遍历逻辑封装在迭代器中,而不是集合类本身
- 支持不同的遍历方式:可以为同一个集合提供不同的迭代器,实现不同的遍历方式
- 解耦集合与遍历:集合类只负责数据的存储,迭代器负责数据的访问
应用场景
- 当需要遍历一个集合对象,但不希望暴露其内部实现时
- 当需要为不同的集合对象提供统一的遍历接口时
- 当需要在不修改集合类的情况下,增加新的遍历方式时
- 当集合类的内部结构复杂,希望简化客户端对集合的访问时
结构
迭代器模式包含以下角色:
- 迭代器(Iterator):定义访问和遍历元素的接口
- 具体迭代器(Concrete Iterator):实现迭代器接口,完成对集合对象的遍历
- 集合(Aggregate):定义创建迭代器对象的接口
- 具体集合(Concrete Aggregate):实现集合接口,创建相应的迭代器对象
实现示例
1. 基本迭代器模式实现
java
// 迭代器接口
public interface Iterator<E> {
boolean hasNext(); // 检查是否还有下一个元素
E next(); // 获取下一个元素
default void remove() { // 移除当前元素(默认实现)
throw new UnsupportedOperationException("不支持删除操作");
}
}
// 集合接口
public interface Aggregate<E> {
Iterator<E> createIterator(); // 创建迭代器对象
}
// 具体集合:数组列表
public class ConcreteAggregate<E> implements Aggregate<E> {
private Object[] elements; // 存储元素的数组
private int size = 0; // 当前元素个数
private static final int DEFAULT_CAPACITY = 10; // 默认容量
public ConcreteAggregate() {
elements = new Object[DEFAULT_CAPACITY];
}
public ConcreteAggregate(int capacity) {
elements = new Object[capacity > 0 ? capacity : DEFAULT_CAPACITY];
}
// 添加元素
public void add(E element) {
ensureCapacity(); // 确保数组有足够的空间
elements[size++] = element;
}
// 获取元素
@SuppressWarnings("unchecked")
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引超出范围: " + index);
}
return (E) elements[index];
}
// 获取元素个数
public int size() {
return size;
}
// 确保数组有足够的空间
private void ensureCapacity() {
if (size == elements.length) {
Object[] newElements = new Object[elements.length * 2];
System.arraycopy(elements, 0, newElements, 0, size);
elements = newElements;
}
}
// 创建迭代器
@Override
public Iterator<E> createIterator() {
return new ConcreteIterator<>();
}
// 具体迭代器
private class ConcreteIterator<E> implements Iterator<E> {
private int cursor = 0; // 当前游标位置
private int lastRet = -1; // 上一次返回元素的索引
@Override
public boolean hasNext() {
return cursor < size; // 检查游标是否小于元素个数
}
@SuppressWarnings("unchecked")
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException("没有更多元素");
}
lastRet = cursor;
return (E) elements[cursor++]; // 返回当前元素,并将游标向前移动
}
@Override
public void remove() {
if (lastRet < 0) {
throw new IllegalStateException("在next()调用之前不能调用remove()");
}
// 删除lastRet位置的元素
int numMoved = size - lastRet - 1;
if (numMoved > 0) {
System.arraycopy(elements, lastRet + 1, elements, lastRet, numMoved);
}
elements[--size] = null; // 释放最后一个位置的引用
cursor = lastRet; // 更新游标位置
lastRet = -1; // 重置lastRet
}
}
}
// 客户端
public class IteratorPatternDemo {
public static void main(String[] args) {
// 创建集合对象
ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();
// 添加元素
aggregate.add("元素1");
aggregate.add("元素2");
aggregate.add("元素3");
aggregate.add("元素4");
aggregate.add("元素5");
// 获取迭代器
Iterator<String> iterator = aggregate.createIterator();
// 使用迭代器遍历集合
System.out.println("使用迭代器遍历集合:");
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// 测试remove方法
System.out.println("\n测试remove方法:");
iterator = aggregate.createIterator();
while (iterator.hasNext()) {
String element = iterator.next();
if (element.equals("元素3")) {
iterator.remove(); // 删除元素3
System.out.println("删除了: " + element);
}
}
// 再次遍历集合
System.out.println("\n删除元素后的集合:");
iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 获取集合大小
System.out.println("\n集合大小: " + aggregate.size());
}
}2. 双向迭代器实现
java
// 双向迭代器接口
public interface BidirectionalIterator<E> extends Iterator<E> {
boolean hasPrevious(); // 检查是否还有前一个元素
E previous(); // 获取前一个元素
}
// 支持双向迭代的集合接口
public interface BidirectionalAggregate<E> extends Aggregate<E> {
BidirectionalIterator<E> createBidirectionalIterator(); // 创建双向迭代器
}
// 具体双向集合
public class BidirectionalConcreteAggregate<E> implements BidirectionalAggregate<E> {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_CAPACITY = 10;
public BidirectionalConcreteAggregate() {
elements = new Object[DEFAULT_CAPACITY];
}
public BidirectionalConcreteAggregate(int capacity) {
elements = new Object[capacity > 0 ? capacity : DEFAULT_CAPACITY];
}
// 添加元素
public void add(E element) {
ensureCapacity();
elements[size++] = element;
}
// 获取元素
@SuppressWarnings("unchecked")
public E get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException("索引超出范围: " + index);
}
return (E) elements[index];
}
// 获取元素个数
public int size() {
return size;
}
// 确保容量
private void ensureCapacity() {
if (size == elements.length) {
Object[] newElements = new Object[elements.length * 2];
System.arraycopy(elements, 0, newElements, 0, size);
elements = newElements;
}
}
// 创建普通迭代器
@Override
public Iterator<E> createIterator() {
return new ConcreteIterator<>();
}
// 创建双向迭代器
@Override
public BidirectionalIterator<E> createBidirectionalIterator() {
return new BidirectionalConcreteIterator<>();
}
// 普通迭代器实现(同前面的实现)
private class ConcreteIterator<E> implements Iterator<E> {
private int cursor = 0;
private int lastRet = -1;
@Override
public boolean hasNext() {
return cursor < size;
}
@SuppressWarnings("unchecked")
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException("没有更多元素");
}
lastRet = cursor;
return (E) elements[cursor++];
}
@Override
public void remove() {
if (lastRet < 0) {
throw new IllegalStateException("在next()调用之前不能调用remove()");
}
int numMoved = size - lastRet - 1;
if (numMoved > 0) {
System.arraycopy(elements, lastRet + 1, elements, lastRet, numMoved);
}
elements[--size] = null;
cursor = lastRet;
lastRet = -1;
}
}
// 双向迭代器实现
private class BidirectionalConcreteIterator<E> implements BidirectionalIterator<E> {
private int cursor = 0; // 当前游标位置
private int lastRet = -1; // 上一次返回元素的索引
@Override
public boolean hasNext() {
return cursor < size;
}
@SuppressWarnings("unchecked")
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException("没有更多元素");
}
lastRet = cursor;
return (E) elements[cursor++];
}
@Override
public boolean hasPrevious() {
return cursor > 0;
}
@SuppressWarnings("unchecked")
@Override
public E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException("没有更多元素");
}
lastRet = --cursor;
return (E) elements[cursor];
}
@Override
public void remove() {
if (lastRet < 0) {
throw new IllegalStateException("在next()或previous()调用之前不能调用remove()");
}
int numMoved = size - lastRet - 1;
if (numMoved > 0) {
System.arraycopy(elements, lastRet + 1, elements, lastRet, numMoved);
}
elements[--size] = null;
if (cursor > lastRet) {
cursor--;
}
lastRet = -1;
}
}
}
// 双向迭代器演示
public class BidirectionalIteratorDemo {
public static void main(String[] args) {
// 创建双向集合
BidirectionalConcreteAggregate<String> aggregate = new BidirectionalConcreteAggregate<>();
// 添加元素
aggregate.add("元素1");
aggregate.add("元素2");
aggregate.add("元素3");
aggregate.add("元素4");
aggregate.add("元素5");
// 获取双向迭代器
BidirectionalIterator<String> iterator = aggregate.createBidirectionalIterator();
// 正向遍历
System.out.println("正向遍历:");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 反向遍历
System.out.println("\n反向遍历:");
while (iterator.hasPrevious()) {
System.out.println(iterator.previous());
}
// 混合遍历(先正向,再反向,再正向)
System.out.println("\n混合遍历:");
// 正向遍历到第3个元素
for (int i = 0; i < 3 && iterator.hasNext(); i++) {
System.out.println("正向: " + iterator.next());
}
// 反向遍历到第1个元素
while (iterator.hasPrevious()) {
System.out.println("反向: " + iterator.previous());
}
// 再次正向遍历
System.out.println("\n再次正向遍历:");
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}实际应用示例:员工信息管理系统
下面是一个实际应用的例子,展示如何使用迭代器模式实现员工信息管理系统:
java
import java.util.HashMap;
import java.util.Map;
// 员工类
public class Employee {
private String id; // 员工ID
private String name; // 员工姓名
private String department; // 部门
private double salary; // 薪资
public Employee(String id, String name, String department, double salary) {
this.id = id;
this.name = name;
this.department = department;
this.salary = salary;
}
// getter方法
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getDepartment() {
return department;
}
public double getSalary() {
return salary;
}
// setter方法
public void setName(String name) {
this.name = name;
}
public void setDepartment(String department) {
this.department = department;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "员工{" +
"ID='" + id + '\'' +
", 姓名='" + name + '\'' +
", 部门='" + department + '\'' +
", 薪资=" + salary +
'}';
}
}
// 迭代器接口(针对员工的迭代器)
public interface EmployeeIterator {
boolean hasNext(); // 检查是否还有下一个员工
Employee next(); // 获取下一个员工
void remove(); // 移除当前员工
}
// 员工集合接口
public interface EmployeeAggregate {
void addEmployee(Employee employee); // 添加员工
void removeEmployee(String employeeId); // 移除员工
EmployeeIterator createIterator(); // 创建迭代器
EmployeeIterator createDepartmentIterator(String department); // 创建按部门过滤的迭代器
}
// 具体员工集合:使用HashMap存储员工
public class EmployeeDirectory implements EmployeeAggregate {
private Map<String, Employee> employees; // 使用ID作为键,员工对象作为值
public EmployeeDirectory() {
employees = new HashMap<>();
}
@Override
public void addEmployee(Employee employee) {
employees.put(employee.getId(), employee);
}
@Override
public void removeEmployee(String employeeId) {
employees.remove(employeeId);
}
@Override
public EmployeeIterator createIterator() {
return new AllEmployeeIterator();
}
@Override
public EmployeeIterator createDepartmentIterator(String department) {
return new DepartmentEmployeeIterator(department);
}
// 获取员工总数
public int getEmployeeCount() {
return employees.size();
}
// 具体迭代器:遍历所有员工
private class AllEmployeeIterator implements EmployeeIterator {
private java.util.Iterator<Employee> iterator; // 使用Java内置的Iterator
private Employee currentEmployee; // 当前员工
public AllEmployeeIterator() {
iterator = employees.values().iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Employee next() {
currentEmployee = iterator.next();
return currentEmployee;
}
@Override
public void remove() {
if (currentEmployee != null) {
iterator.remove();
currentEmployee = null;
}
}
}
// 具体迭代器:按部门过滤员工
private class DepartmentEmployeeIterator implements EmployeeIterator {
private String department; // 目标部门
private Employee[] departmentEmployees; // 存储部门员工的数组
private int position = 0; // 当前位置
private int currentIndex = -1; // 当前员工索引
public DepartmentEmployeeIterator(String department) {
this.department = department;
// 初始化部门员工数组
initDepartmentEmployees();
}
// 初始化部门员工数组
private void initDepartmentEmployees() {
// 先计算部门员工数量
int count = 0;
for (Employee employee : employees.values()) {
if (employee.getDepartment().equals(department)) {
count++;
}
}
// 创建数组并填充
departmentEmployees = new Employee[count];
int index = 0;
for (Employee employee : employees.values()) {
if (employee.getDepartment().equals(department)) {
departmentEmployees[index++] = employee;
}
}
}
@Override
public boolean hasNext() {
return position < departmentEmployees.length;
}
@Override
public Employee next() {
if (!hasNext()) {
throw new NoSuchElementException("没有更多员工");
}
currentIndex = position;
return departmentEmployees[position++];
}
@Override
public void remove() {
if (currentIndex < 0) {
throw new IllegalStateException("在next()调用之前不能调用remove()");
}
// 从Map中移除员工
Employee employeeToRemove = departmentEmployees[currentIndex];
employees.remove(employeeToRemove.getId());
// 重新初始化部门员工数组
initDepartmentEmployees();
// 调整位置
position = currentIndex;
currentIndex = -1;
}
}
}
// 客户端:员工管理系统
public class EmployeeManagementSystem {
public static void main(String[] args) {
// 创建员工目录
EmployeeDirectory directory = new EmployeeDirectory();
// 添加员工
directory.addEmployee(new Employee("E001", "张三", "开发部", 9000));
directory.addEmployee(new Employee("E002", "李四", "开发部", 8500));
directory.addEmployee(new Employee("E003", "王五", "市场部", 7500));
directory.addEmployee(new Employee("E004", "赵六", "市场部", 7000));
directory.addEmployee(new Employee("E005", "钱七", "人事部", 8000));
// 遍历所有员工
System.out.println("=== 所有员工 ===");
EmployeeIterator allIterator = directory.createIterator();
while (allIterator.hasNext()) {
System.out.println(allIterator.next());
}
// 遍历开发部员工
System.out.println("\n=== 开发部员工 ===");
EmployeeIterator devIterator = directory.createDepartmentIterator("开发部");
while (devIterator.hasNext()) {
System.out.println(devIterator.next());
}
// 遍历市场部员工
System.out.println("\n=== 市场部员工 ===");
EmployeeIterator marketIterator = directory.createDepartmentIterator("市场部");
while (marketIterator.hasNext()) {
System.out.println(marketIterator.next());
}
// 测试删除功能
System.out.println("\n=== 测试删除功能 ===");
devIterator = directory.createDepartmentIterator("开发部");
while (devIterator.hasNext()) {
Employee employee = devIterator.next();
if (employee.getId().equals("E002")) {
devIterator.remove();
System.out.println("删除了员工: " + employee.getId());
break;
}
}
// 再次遍历开发部员工
System.out.println("\n=== 删除后的开发部员工 ===");
devIterator = directory.createDepartmentIterator("开发部");
while (devIterator.hasNext()) {
System.out.println(devIterator.next());
}
// 获取员工总数
System.out.println("\n员工总数: " + directory.getEmployeeCount());
}
}优缺点
优点
- 提供统一的遍历接口:客户端可以使用相同的方式遍历不同类型的集合
- 封装遍历逻辑:将集合的遍历逻辑封装在迭代器中,使集合类更加专注于数据的存储和管理
- 支持不同的遍历方式:可以为同一个集合提供不同的迭代器,实现不同的遍历方式
- 符合单一职责原则:集合类负责数据的存储,迭代器负责数据的访问
缺点
- 增加了类的数量:每个集合类可能需要对应多个迭代器类,增加了系统中类的数量
- 可能会增加系统的复杂性:特别是当需要支持多种遍历方式时
- 对于简单的集合,使用迭代器可能会显得有些繁琐:例如,对于简单的数组,直接使用for循环可能更加简单
与其他模式的关系
- 迭代器模式与工厂方法模式:集合类创建迭代器的过程可以看作是工厂方法模式的应用
- 迭代器模式与组合模式:迭代器模式常用于遍历组合模式中的对象树
- 迭代器模式与访问者模式:两者都可以用于遍历集合,但访问者模式更关注对元素的操作,而迭代器模式更关注遍历本身
总结
迭代器模式是一种常用的行为型设计模式,它提供了一种方法来访问一个容器对象中的各个元素,而又不暴露该对象的内部表示。迭代器模式将遍历逻辑从集合类中分离出来,使集合类更加专注于数据的存储和管理。在实际应用中,Java等编程语言的集合框架都内置了对迭代器模式的支持,使得我们可以方便地遍历各种集合对象。