Iterator Pattern in "Design Patterns"

1. What is the iterator pattern?

In actual development, we may need to traverse the entire integration object in different ways for different needs, but we do not want the abstract interface layer of the collection container to be filled with various traversal operations. At this time, we need a An iterator that can complete the following functions:

  • (1) Traverse a collection object
  • (2) There is no need to understand the internal structure of the aggregate object
  • (3) Provide a variety of different traversal methods

The Iterator pattern provides a way to access individual elements in a collection without exposing its internal representation. Giving the responsibility of walking between elements to iterators instead of collection objects simplifies the implementation of collection containers and allows the collection container to focus on what it should focus on, which is more in line with the single responsibility principle. 

2. UML structure diagram

  • Iterator: Abstract iterator, which provides a method for walking between collection container elements.
  • ConcreteIterator: A specific iterator that can traverse specific collection containers. Each collection container should correspond to a specific iterator.
  • Aggregate: abstract container class
  • ConcreteAggregate: A concrete container class that implements the creatorIterator() method and returns the iterator of the aggregate object.

3. Code implementation 

3.1. UML result diagram

 

3.2. Case 1

Here I handwrite a simple java iterator

Collection_Interface

package com.company.Iterator.v5;

public interface Collection_ {
    void add(Object o);
    int size();

    Iterator_ iterator();
}

Iterator interface 

package com.company.Iterator.v5;

public interface Iterator_ {
    boolean hasNext();

    Object next();
}

ArrayList_class

package com.company.Iterator.v5;


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class ArrayList_ implements Collection_ {
    Object[] objects = new Object[10];
    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
    private int index = 0;
    public void add(Object o) {
        if(index == objects.length) {
            Object[] newObjects = new Object[objects.length*2];
            System.arraycopy(objects, 0, newObjects, 0, objects.length);
            objects = newObjects;
        }

        objects[index] = o;
        index ++;
    }

    public int size() {
        return index;
    }

    @Override
    public Iterator_ iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator implements Iterator_{

        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
            if(currentIndex >= index) return false;
            return true;
        }

        @Override
        public Object next() {
            Object o = objects[currentIndex];
            currentIndex ++;
            return o;
        }
    }
}

main function

package com.company.Iterator.v5;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 * v4:如何对容器遍历呢?
 * v4:用一种统一的遍历方式,要求每一个容器都要提供Iterator的实现类
 *    作业:实现LinkedList的Iterator
 */

public class Main {
    public static void main(String[] args) {
        Collection_ list = new ArrayList_();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());

        //这个接口的调用方式:
        Iterator_ it = list.iterator();
        while(it.hasNext()) {
            Object o = it.next();
            System.out.println(o);
        }
    }
}

operation result 

3.3. Case 2

Add generics (improved version)

Collection_Interface

package com.company.Iterator.v7;

public interface Collection_<E> {
    void add(E o);
    int size();

    Iterator_ iterator();
}

Iterator interface 

package com.company.Iterator.v7;

public interface Iterator_<E> { //Element //Type //K //Value V Tank
    boolean hasNext();

    E next(); //Tank next() Iterator_<Tank> it = ... Tank t = it.next();
}

ArrayList_class

package com.company.Iterator.v7;


/**
 * 相比数组,这个容器不用考虑边界问题,可以动态扩展
 */
class ArrayList_<E> implements Collection_<E> {
    E[] objects = (E[])new Object[10];
    //objects中下一个空的位置在哪儿,或者说,目前容器中有多少个元素
    private int index = 0;
    public void add(E o) {
        if(index == objects.length) {
            E[] newObjects = (E[])new Object[objects.length*2];
            System.arraycopy(objects, 0, newObjects, 0, objects.length);
            objects = newObjects;
        }

        objects[index] = o;
        index ++;
    }

    public int size() {
        return index;
    }

    @Override
    public Iterator_<E> iterator() {
        return new ArrayListIterator();
    }

    private class ArrayListIterator<E> implements Iterator_<E> {

        private int currentIndex = 0;

        @Override
        public boolean hasNext() {
            if(currentIndex >= index) return false;
            return true;
        }

        @Override
        public E next() {
            E o = (E)objects[currentIndex];
            currentIndex ++;
            return o;
        }
    }
}

main function

package com.company.Iterator.v7;

/**
 * v1:构建一个容器,可以添加对象
 * v2:用链表来实现一个容器
 * v3:添加容器的共同接口,实现容器的替换
 * v4:如何对容器遍历呢?
 * v4:用一种统一的遍历方式,要求每一个容器都要提供Iterator的实现类
 *    作业:实现LinkedList的Iterator
 * v6:JDK的容器实现
 * v7:实现泛型版本
 */

public class Main {
    public static void main(String[] args) {
        Collection_<String> list = new ArrayList_<>();
        for(int i=0; i<15; i++) {
            list.add(new String("s" + i));
        }
        System.out.println(list.size());

        //这个接口的调用方式:
        Iterator_<String> it = list.iterator();
        while(it.hasNext()) {
            String o = it.next();
            System.out.println(o);
        }
    }
}

operation result

4. Summary of iterator pattern

4.1. Advantages

(1) The iterator pattern simplifies the interface of the collection. The iterator has the traversal function, so that the interface of the collection does not need to reimplement the traversal function.

(2) Each aggregation object can have one or more iterator sub-objects, and the iteration status of each iterator can be independent of each other. Therefore, an aggregate object can have several iterations in progress at the same time.

(3) Since the traversal algorithm is encapsulated in the iteration sub-role, the iteration algorithm can change independently of the aggregation role.

(4) Better encapsulation, accessing elements of a collection object without exposing the internal representation of the container.

4.2. Disadvantages

(1) The iterator pattern separates the responsibilities of storing data and traversing data. Adding a new aggregate class requires adding a new iterator class. The number of classes increases in pairs, which increases the complexity of the system to a certain extent.

(2) For relatively simple traversal, using the iterator mode seems more cumbersome. For example, ArrayList can be traversed directly using the for loop + get() method;

(3) The design of abstract iterators is difficult, and the future expansion of the system needs to be fully considered. For example, the JDK built-in iterator Iterator cannot implement reverse traversal. If reverse traversal needs to be implemented, it can only be achieved through its subclass ListIterator, etc. The ListIterator iterator cannot be used to operate aggregate objects of Set type. When customizing iterators, it's not easy to create a well-thought-out abstract iterator.

4.3. Applicable scenarios

(1) Access the contents of a collection object without exposing its internal representation.

(2) It is necessary to provide multiple traversal methods for collection objects.

(3) Provide a unified interface for traversing different aggregate structures.

PS: Because containers and iterators are so closely related, most languages ​​provide iterators when implementing containers, and the containers and iterators provided by these languages ​​can meet our needs in most cases. , so it is still relatively rare that we need to practice the iterator pattern ourselves. We only need to use the existing containers and iterators in the language.

Reference article:  Behavioral type of Java design pattern: iterator pattern_Zhang Weipeng's blog-CSDN blog_java iterator pattern

Guess you like

Origin blog.csdn.net/m0_50370837/article/details/126331605
Recommended