likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 2

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

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

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

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

迭代器模式的优点:

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

迭代器模式的缺点:

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

下面是一个使用 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() 方法遍历集合中的元素。

场景举例

场景一:遍历集合

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

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

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为例,我们可以使用迭代器模式来实现对数据库表的查询操作:

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