Also known as Cursor.
As stated in GoF, p257 :
Provide a way to access the elements of an aggregate object sequentially, without exposing its underlying representation.
That is, give a sequential access to various containers (stacks, vector, list, array, map...)
You should use the Iterator pattern in the following cases :
- When you have a collection that has a complex structure and you want to hide its complexity from clients. You can have various reasons to do so.
- Security : A client could be able to perform careless or malicious actions on the collection. convenience...
- Convenience : Provide the client with simple methods to access elements will improve the clarity and the readability of the produced code.
- To reduce code duplication : The code for the traversal of the collection can indeed be duplicated alot in different places of the application.
- When you want to iterate through different containers or when you actually do not know the type of containers you will have. (See Polymorphic iteration)
Participants
- Iterator : Defines an interface for accessing/traversing elements.
- ConcreteIterator :
- Implements the Iterator interface.
- Keeps track of the current position in the traversal.
- Aggregate : Defines an interface for creating an Iterator object.
- ConcreteAggregate : Implements the Iterator creation interface to return an instance of the proper ConcreteIterator.
How to implement
- Declare the Iterator interface with - at least - a method to get the next element of the Aggregate.
- Declare the ConcreteIterator that implements Iterator for the collections you want to use.
- Implement the interface of Aggregate responsible for creating an Iterator. (begin(), end() ...).
- Replace the client code traversal codes with iterators.
Note : UML class diagram taken from here
Pros
- Single responsability principle : Clean up client code for the collection iterations.
- Open/closed principle : You can simply implement new kinds of structures and their corresponding iterators interface and pass them to an existing code without breaking it.
- Perform multiple parallel iterations : Iterators contain their own iteration state.
Cons
- Using an iterator may be less efficient than going through elements of some specialized collections directly.
Here are some usefull ressources :
- The cppreference documentation.
- A complete example
- w3sdesign
- A Refactoring guru article.
