The iterator design pattern is typically used to iterate over elements in a collection.
Suppose we have a bookshelf with a lot of books on it. We wish to print out the names of all the books in this shelf. This is where the iterator design pattern comes in.
Let’s use UML to draw the class diagram first:
To understand this diagram, we need to understand the following concepts. It’s easy to break it down and understand it.
1 Basic Concepts
(1) Class composition
A class is divided into three main parts: class name, attribute list, and action list.
The format of each attribute or operation is :[Visibility permission] [attribute or method name]:[Return type] [Chinese description]. The [Chinese description] here is not available in UML, so the Chinese description is added here for easy understanding.
The visibility permission is 1:
The prefix symbol | instructions |
---|
- | public
| protected
- | private
To the default package | permissions
(2) Interface
In order to distinguish the interface from the class in the class diagram, we add the interface name<<interface>>
Identifier:
(3) Class relationship
Two kinds of relationships emerge: implementation and aggregation.
An implementation relationship indicates that a class implements an interface, represented by a dotted hollow triangle with an arrow pointing to the interface:
The aggregation relationship represents the relationship between the whole and the parts. But it is a weak relationship, meaning that the life cycle between the two classes is different. For example, the relationship between bookshelves and books, even if there are no books on the bookshelves, the bookshelves still exist.
Aggregative relationships are often confused with combinatorial relationships because they can both represent wholes and parts. The essential difference between the two is whether the life cycles of the whole and the parts are consistent.
For example, the relationship between various parts in a car and the car is a combinatorial relationship. Once the car is scrapped, these parts are meaningless. So it’s a strong relationship, it’s a contains- A relationship.
The relationship between the bookshelf and the book in our example is not so strong, they are aggregated. Bookshelves can also contain other things, such as decorations, even if they do not contain books.
2 implementation
The example is implemented in the Java language.
First we define two interfaces, one for collections and one for iterators.
(1) Collection interface
Public interface Aggregate {/** ** return */ Iterator Iterator (); }Copy the code
The collection interface defines only one method that returns an iterator for a traversable collection.
(2) Iterator interface
Public interface Iterator {@return */ Boolean hasNext(); /** * get next element * @return */ Object next(); }Copy the code
The iterator interface defines two methods, one to determine the existence of the next element and one to get the next element. These are the basic methods of iterators.
We then define the respective implementation classes for iterators and collections, namely the bookshelf and bookshelf iterator classes. The bookshelf class contains methods that return the iterator class; The iterator class requires the bookshelf class as an initial input. I’m in you, I’m in you.
(3) Bookshelf iterator
Leaving the iterator to iterate over the iteration is also a form of decoupling.
public class BookShelfIterator implements Iterator { private BookShelf bookShelf; private int index; public BookShelfIterator(BookShelf bookShelf) { this.bookShelf = bookShelf; this.index = 0; } public boolean hasNext() { if (index < bookShelf.getLength()) { return true; } else { return false; } } public Object next() { Book book = bookShelf.getBookAt(index); index++; return book; }}Copy the code
(4) Bookshelf
Bookshelf to achieve the collection interface, bookshelf can be placed a lot of things, in essence is a collection.
public class BookShelf implements Aggregate { private Book[] books; private int last = 0; public BookShelf(int maxsize) { this.books = new Book[maxsize]; } public Book getBookAt(int index) { return books[index]; } public void appendBook(Book book) { this.books[last] = book; last++; } public int getLength() { return last; } public Iterator iterator() { return new BookShelfIterator(this); }}Copy the code
The key point here is the iterator() method, which returns the BookShelfIterator book iterator class. This method accepts a BookShelf as an input. BookShelf is needed inside the iterator to implement the hasNext() and next() methods.
Note that the next() method returns the current element and points the index to the next element.
(5) book
Finally, define the book class as an element in the collection.
public class Book { private String name; public Book(String name) { this.name = name; } public String getName() { return name; }}Copy the code
3 the use of
public class Main { public static void main(String[] args) { BookShelf bookShelf = new BookShelf(3); AppendBook (new Book(" weightless person ")); Bookshelf. appendBook(new Book(" Kew Gardens Story ")); AppendBook (New Book(" Annie Carson poems ")); Iterator it = bookShelf.iterator(); while (it.hasNext()) { Book book = (Book) it.next(); System.out.println(book.getName()); }}}Copy the code
Running results:
Iterator design pattern
The iterator design pattern abstract class diagram can be summarized from the previous example:
The key is to define two interfaces, one for collections and the other for iterators used to iterate over collection elements. The collection contains multiple elements. The iterator implementation class owns the collection implementation class object in order to iterate. The collection implementation class provides methods to return iterators so that outer clients can get the iterator and perform element iteration.
5 think
One might ask, why bother, just put the book on the list?
Lists (such as arrayLists) are essentially implemented using the iterator pattern:
An ArrayList is a kind of collection that implements multiple iterators inside.
The iterator design pattern decouples collections from iterations. This does not affect the iteration process whether the collection uses arrays, lists, or other data structures. Iterators do only the traversal and fulfill a single responsibility.
Iterators can also apply different iteration rules, such as forward iteration, backward iteration, or even jump iteration. Changes in iteration rules will not affect the internal implementation of the collection.
- UML class diagrams.
- Jie Chenghao (author), Yang Wenxuan (translator). Graphic Design Patterns [M]. Posts and Telecommunications Press, 2017:34-44.