通俗易懂设计模式(迭代器模式)

迭代器模式是一种行为型设计模式,它提供了一种遍历集合元素的统一接口,使得在不暴露集合内部结构的情况下可以顺序访问其中的每个元素。迭代器模式具有以下特点:

  1. 提供一种遍历集合元素的统一接口。
  2. 隐藏集合内部结构,客户端不需要关心集合的具体实现。
  3. 可以同时遍历多个集合,只要它们提供相同的迭代器接口。

迭代器模式的主要角色有:

  1. 迭代器(Iterator):定义遍历集合元素的接口,包括获取下一个元素、判断是否有下一个元素等方法。
  2. 具体迭代器(Concrete Iterator):实现迭代器接口,负责遍历集合的具体实现。
  3. 集合(Aggregate):定义创建迭代器的接口,即返回一个迭代器对象。
  4. 具体集合(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() 方法遍历集合中的元素。

迭代器模式的优点:

  1. 遍历集合元素时,不需要关心集合的内部结构,只需要关心迭代器的接口。
  2. 可以同时遍历多个集合,只要它们提供相同的迭代器接口。
  3. 可以在遍历过程中,对集合进行修改,而不会影响遍历的正确性。

迭代器模式的缺点:

  1. 需要为每个集合类提供一个具体的迭代器类,增加了代码的复杂性。
  2. 迭代器模式不支持并发访问,如果多个线程同时遍历同一个集合,可能会出现数据不一致的问题。

场景举例

场景一:遍历集合

迭代器模式是一种非常有用的设计模式,它提供了一种在不暴露集合内部结构的情况下,顺序访问集合中元素的方法。在实际开发中,我们经常需要遍历各种类型的集合,如数组、列表、栈、队列等。使用迭代器模式可以使代码更加简洁、灵活和可维护。

以遍历一个整数数组为例,我们可以使用迭代器模式来实现:

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 类查询数据库表,并使用迭代器遍历查询结果集。

相关推荐
李白的粉7 分钟前
基于springboot的在线教育系统
java·spring boot·毕业设计·课程设计·在线教育系统·源代码
码农10087号19 分钟前
Hot100方法及易错点总结2
java
iuyou️1 小时前
Spring Boot知识点详解
java·spring boot·后端
北辰浮光1 小时前
[Mybatis-plus]
java·开发语言·mybatis
一弓虽1 小时前
SpringBoot 学习
java·spring boot·后端·学习
南客先生1 小时前
互联网大厂Java面试:RocketMQ、RabbitMQ与Kafka的深度解析
java·面试·kafka·rabbitmq·rocketmq·消息中间件
ai大佬1 小时前
Java 开发玩转 MCP:从 Claude 自动化到 Spring AI Alibaba 生态整合
java·spring·自动化·api中转·apikey
Mr__Miss2 小时前
面试踩过的坑
java·开发语言
爱喝一杯白开水2 小时前
POI从入门到上手(一)-轻松完成Apache POI使用,完成Excel导入导出.
java·poi
向哆哆2 小时前
Java 安全:如何防止 DDoS 攻击?
java·安全·ddos