Definition: Provides a method to access various elements in a container object without exposing the internal details of the object.
Type: Behavioral Pattern
Class diagram:
If you want to ask the most commonly used mode in Java, the answer is not the singleton mode, nor the factory mode, nor the strategy mode, but the iterator mode. Let’s take a look at a piece of code first:
public static void print(Collection coll){ Iterator it = coll.iterator(); while(it.hasNext()){ String str = (String)it.next(); System.out.println(str); } } The function of this method is to print a string collection loop, and the iterator pattern is used in iterator pattern. The Java language has fully implemented the iterator pattern. Iterator translated into Chinese means iterator. When it comes to iterators, first of all, it is related to sets. Sets are also called aggregates, containers, etc. We can regard sets as containers that can contain objects. For example, List, Set, Map, and even arrays can be called sets. The function of iterators is to traverse the objects in the container one by one.
The structure of iterator pattern
Abstract container: Generally, iterator() method is provided, such as Collection interface, List interface, Set interface, etc. in Java.
Specific container: It is the concrete implementation class of abstract containers, such as the ordered list of List interface to implement ArrayList, the linked list of List interface to implement LinkList, the hash list of Set interface to implement HashSet, etc.
Abstract iterator: define the method required to traverse elements. Generally speaking, there are three methods: get the first() method of the first element, get the next() method of the next element, determine whether the method of traversal ends isDone() (or hasNext()), remove() of the current object,
Iterator implementation: implements the methods defined in the iterator interface to complete the iteration of the collection.
Give an example
Since the regulations of the iterator mode itself are relatively loose, the specific implementation is diverse. Let’s give only one example here, and we cannot present the implementation methods one by one. Therefore, before giving an example, let’s list the implementation methods of the next iterator pattern.
1. The iterator role defines the interface for traversal, but does not specify who controls the iteration. In the application of Java collection, the process of traversal is controlled by the client program, which is called an external iterator; another implementation method is to control iterator itself, which is called an internal iterator. External iterators are flexible and powerful than internal iterators, and internal iterators are very weak in the Java locale environment.
2. There is no provision for who will implement the traversal algorithm in the iterator mode. It seems to be natural to implement in the iterator role. Because it is convenient for different traversal algorithms to be used on a container, it is also convenient for applying a traversal algorithm to different containers. But this destroys the encapsulation of the container - the container role must disclose its own private attributes, which in Java means exposing its own private attributes to other classes.
Then let's put it in the container role to implement it. In this way, the iterator role is overridden to only store a function that traverses the current location. But the traversal algorithm is tightly tied to a specific container.
In the application of Java Collection, the specific iterator role provided is the internal class defined in the container role. This protects the container's packaging. But at the same time, the container also provides a traversal algorithm interface, and you can extend your own iterator.
OK, let's take a look at how the iterator in Java Collection is implemented.
//Iterator role, only defines the traversal interface public interface Iterator { boolean hasNext(); Object next(); void remove();}//Container role, take List as an example here. It is just an interface, so it will not be listed. The specific container role is ArrayList and other classes that implement the List interface. To highlight the key points, we refer to the content related to the iterator //The specific iterator role is derived in the form of an internal class. AbstractList exists to extract the common parts of each specific container role. public abstract class AbstractList extends AbstractCollection implements List {... //This is the factory method responsible for creating specific iterator roles public Iterator() { return new Itr();}//As the specific iterator role of internal class Itr implements Iterator { int cursor = 0; int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public Object next() { checkForComodification(); try { Object next = get(cursor); lastRet = cursor++; return next; } catch(IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } public void remove() { if (lastRet == -1) throw new IllegalStateException(); checkForComodification(); try { AbstractList.this.remove(lastRet); if (lastRet < cursor) cursor--; lastRet = -1; expectedModCount = modCount; } catch(IndexOutOfBoundsException e) { throw new ConcurrentModificationException(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }}As for the use of iterator mode. As listed in the introduction, the client program needs to obtain the specific container role first, and then obtain the specific iterator role through the specific container role. This way, you can use the specific iterator role to traverse the container...
Pros and cons of iterator mode
The advantages of iterator mode are:
The traversal method has been simplified, and it is still quite troublesome to traverse the object collection. For arrays or ordered lists, we can still obtain them through cursors, but users need to traverse the objects by themselves on the premise that they have a clear understanding of the collection. However, for the hash table, it is more troublesome to traverse the user. After introducing the iterator method, it is much easier for users to use.
There are many ways to traverse, such as for ordered lists, we can provide two iterators with positive order and reverse order traversal according to needs. Users only need to obtain the iterator we implemented to easily traverse the collection.
The encapsulation is good, and users only need to get an iterator to traverse, but they don’t have to worry about traversal algorithms.
Disadvantages of iterator pattern:
For simple traversals (such as arrays or ordered lists), it is more cumbersome to use iterators, and everyone may feel that, like ArrayList, we would rather use for loops and get methods to traverse the collection.
Applicable scenarios for iterator mode
The iterator pattern is symbiotic and death with the collection. Generally speaking, as long as we implement a collection, we need to provide the iterator of the collection at the same time, just like Collection, List, Set, Map, etc. in Java, these collections have their own iterators. If we want to implement such a new container, of course we also need to introduce an iterator pattern to implement an iterator for our container.
However, since the relationship between containers and iterators is too close, most languages provide iterators when implementing containers, and the containers and iterators provided by these languages can meet our needs in most cases. Therefore, it is relatively rare to practice the iterator pattern by ourselves. We only need to use the existing containers and iterators in the language.