【设计模式】—迭代器模式([design mode] – iterator mode)

1.概述

定义:

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

2.结构迭代器模式主要包含以下角色:

抽象聚合(Aggregate)角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口。具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、next() 等方法。具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。3.案例【例】定义一个可以存储学生对象的容器对象,将遍历该容器的功能交由迭代器实现,涉及到的类如下:

代码如下:

定义迭代器接口,声明hasNext、next方法

public interface StudentIterator { boolean hasNext(); Student next();}定义具体的迭代器类,重写所有的抽象方法

public class StudentIteratorImpl implements StudentIterator { private List<Student> list; private int position = 0;

public StudentIteratorImpl(List<Student> list) { this.list = list; }

@Override public boolean hasNext() { return position < list.size(); }

@Override public Student next() { Student currentStudent = list.get(position); position ++; return currentStudent; }}定义抽象容器类,包含添加元素,删除元素,获取迭代器对象的方法

public interface StudentAggregate { void addStudent(Student student);

void removeStudent(Student student);

StudentIterator getStudentIterator();}定义具体的容器类,重写所有的方法

public class StudentAggregateImpl implements StudentAggregate {

private List<Student> list = new ArrayList<Student>(); // 学生列表

@Override public void addStudent(Student student) { this.list.add(student); }

@Override public void removeStudent(Student student) { this.list.remove(student); }

@Override public StudentIterator getStudentIterator() { return new StudentIteratorImpl(list); }}4.优缺点1,优点:

它支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式。在迭代器模式中只需要用一个不同的迭代器来替换原有迭代器即可改变遍历算法,我们也可以自己定义迭代器的子类以支持新的遍历方式。迭代器简化了聚合类。由于引入了迭代器,在原有的聚合对象中不需要再自行提供数据遍历等方法,这样可以简化聚合类的设计。在迭代器模式中,由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,满足 “开闭原则” 的要求。2,缺点:

增加了类的个数,这在一定程度上增加了系统的复杂性。

5.使用场景当需要为聚合对象提供多种遍历方式时。当需要为遍历不同的聚合结构提供一个统一的接口时。当访问一个聚合对象的内容而无须暴露其内部细节的表示时。JDK源码解析迭代器模式在JAVA的很多集合类中被广泛应用,接下来看看JAVA源码中是如何使用迭代器模式的。

List<String> list = new ArrayList<>();Iterator<String> iterator = list.iterator(); //list.iterator()方法返回的肯定是Iterator接口的子实现类对象while (iterator.hasNext()) { System.out.println(iterator.next());}看完这段代码是不是很熟悉,与我们上面代码基本类似。单列集合都使用到了迭代器,我们以ArrayList举例来说明

List:抽象聚合类ArrayList:具体的聚合类Iterator:抽象迭代器list.iterator():返回的是实现了 Iterator 接口的具体迭代器对象具体的来看看 ArrayList的代码实现

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor; // 下一个要返回元素的索引 int lastRet = -1; // 上一个返回元素的索引 int expectedModCount = modCount;

Itr() {} //判断是否还有元素 public boolean hasNext() { return cursor != size; }

//获取下一个元素 public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } …}这部分代码还是比较简单,大致就是在 iterator 方法中返回了一个实例化的 Iterator 对象。Itr是一个内部类,它实现了 Iterator 接口并重写了其中的抽象方法。

注意:当我们在使用JAVA开发的时候,想使用迭代器模式的话,只要让我们自己定义的容器类实现java.util.Iterable并实现其中的iterator()方法使其返回一个 java.util.Iterator 的实现类就可以了。

————————

1. General

definition:

Provides an object to sequentially access a series of data in an aggregate object without exposing the internal representation of the aggregate object.

2. The structure iterator pattern mainly includes the following roles:

Abstract aggregate role: defines interfaces for storing, adding, deleting aggregate elements, and creating iterator objects. Concrete aggregate role: implement the abstract aggregate class and return an instance of a concrete iterator. Abstract iterator role: defines the interface for accessing and traversing aggregation elements, usually including methods such as hasnext(), next(). Concrete iterator role: implement the methods defined in the abstract iterator interface, complete the traversal of aggregate objects, and record the current location of traversal. 3. Case [example] defines a container object that can store student objects. The function of traversing the container is implemented by the iterator. The classes involved are as follows:

The code is as follows:

Define the iterator interface and declare hasnext and next methods

public interface StudentIterator { boolean hasNext(); Student next();} Define concrete iterator classes and override all abstract methods

public class StudentIteratorImpl implements StudentIterator { private List<Student> list; private int position = 0;

public StudentIteratorImpl(List<Student> list) { this.list = list; }

@Override public boolean hasNext() { return position < list.size(); }

@Override public Student next() { Student currentStudent = list.get(position); position ++; return currentStudent; }} Define abstract container classes, including methods to add elements, delete elements, and obtain iterator objects

public interface StudentAggregate { void addStudent(Student student);

void removeStudent(Student student);

StudentIterator getStudentIterator();} Define specific container classes and override all methods

public class StudentAggregateImpl implements StudentAggregate {

private List<Student> list = new ArrayList<Student>(); // 学生列表

@Override public void addStudent(Student student) { this.list.add(student); }

@Override public void removeStudent(Student student) { this.list.remove(student); }

@Override public StudentIterator getStudentIterator() { return new StudentIteratorImpl(list); }}4.优缺点1,优点:

It supports traversing an aggregate object in different ways, and multiple traversal methods can be defined on the same aggregate object. In the iterator mode, we only need to replace the original iterator with a different iterator to change the traversal algorithm. We can also define the subclass of the iterator to support the new traversal method. Iterators simplify aggregate classes. Due to the introduction of iterator, there is no need to provide data traversal and other methods in the original aggregation object, which can simplify the design of aggregation class. In the iterator mode, due to the introduction of the abstraction layer, it is convenient to add new aggregation classes and iterator classes without modifying the original code to meet the requirements of the “opening and closing principle”. 2. Disadvantages:

The number of classes is increased, which increases the complexity of the system to a certain extent.

5. Use scenario: when it is necessary to provide multiple traversal methods for aggregate objects. When it is necessary to provide a unified interface for traversing different aggregation structures. When accessing the contents of an aggregate object without exposing the representation of its internal details. JDK source code parsing iterator pattern is widely used in many collection classes in Java. Next, let’s see how to use iterator pattern in Java source code.

List< String> list = new ArrayList<& gt; (); Iterator< String> iterator = list. iterator(); // list. The iterator () method must return the sub implementation class object while (iterator. Hasnext()) {system. Out. Println (iterator. Next());} of the iterator interface After reading this code, are you familiar with it? It is basically similar to the code above. Iterators are used in single column collections. Let’s take ArrayList as an example

List: Abstract aggregate classarraylist: concrete aggregate classiterator: Abstract iterator list Iterator (): returns the iterator object that implements the iterator interface. Let’s take a look at the code implementation of ArrayList

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor; // 下一个要返回元素的索引 int lastRet = -1; // 上一个返回元素的索引 int expectedModCount = modCount;

Itr() {} //判断是否还有元素 public boolean hasNext() { return cursor != size; }

//获取下一个元素 public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } …}这部分代码还是比较简单,大致就是在 iterator 方法中返回了一个实例化的 Iterator 对象。Itr是一个内部类,它实现了 Iterator 接口并重写了其中的抽象方法。

Note: when we are developing in Java, if we want to use iterator mode, we just need to let our own defined container class implement Java util. Iteratable and implement the iterator () method to return a Java util. The implementation class of iterator is OK.