Card 02/ 09

ConceptDifficulty: Intermediate1 min

Iterator Pattern Structure: The Class Diagram

An Aggregate creates an Iterator, and the Iterator keeps the position.

Iterator has four participants: an aggregate interface and its concrete class, and an iterator interface and its concrete class. This card reads their roles off the Gang of Four's class diagram, names each one in Python, Java and TypeScript, and explains why the position is kept in the iterator rather than in the collection.

Iterator participants
Each participant and its name in three languages
ParticipantRolePythonJavaTypeScript
AggregateDeclares the method that creates an iterator__iter__Iterable<T>Iterable<T>
ConcreteAggregateHolds the elements and returns an iterator over themA class with __iter__A class implementing IterableA class with [Symbol.iterator]()
IteratorDeclares how to get the next element and how to tell the end__next__, raising StopIteration at the endhasNext() and next()next(), returning { done, value }
ConcreteIteratorKeeps the position and returns elements one at a timeA class with __next__A class implementing IteratorAn object with next()

The Gang of Four's diagram names the iterator's methods first, next, isDone and currentItem; the three languages fold them into one or two methods, and the diagram above uses those.

The position lives in the iterator, not in the aggregate, because two loops over the same collection must not share it. A nested loop that compares every song with every other song walks the playlist twice at once, and each walk needs its own place. Because each call to the aggregate's creating method returns a fresh iterator, each walk has its own position.

The creating method is itself a factory method: the aggregate decides which concrete iterator to build, and the caller sees only the interface.