Iterator Pattern
Access the elements of an aggregate object sequentially without exposing its underlying representation.
Intent & Objective
Provide a uniform way to traverse elements of a complex collection (list, tree, graph) without exposing its internal representation (linked list pointers, hash buckets, binary tree nodes).
"A walking tour provides sequential instructions ('Go here, then next, then next') without requiring you to study the city’s complex sewer and electrical grid."
"Pressing the 'Next Channel' button scrolls through broadcast stations sequentially without needing to know antenna frequencies."
The Problem
Exposing internal collection mechanics to client code, making it impossible to switch collection types without rewriting client loops.
The Solution
Extract the traversal behavior of a collection into a separate object called an iterator with standard `hasNext()` and `next()` methods.
Key Participants & Architectural Roles
Code Samples (Traditional OOP vs Functional Programming)
Available in C++, Python, and JavaParadigm Contrast: Traditional OOP vs Functional / Data-Oriented
In OOP, Iterator uses explicit stateful iterator objects with `next()` and `hasNext()`. In Functional Programming, Iterators are replaced by pure generators, lazy streams, and higher-order fold/map/filter functions.
Advantages
- ✓ Single Responsibility Principle: cleans up client code and collections by moving traversal algorithms into separate classes
- ✓ Open/Closed Principle: implements new types of collections and iterators without breaking existing code
- ✓ Can iterate over the same collection in parallel
Trade-offs
- ✗ Overkill for simple arrays or flat lists
When to Apply
- → When your collection has a complex data structure under the hood, but you want to hide its complexity from clients
- → To reduce duplication of traversal code across your app
When to Avoid
- ! When iterating over standard contiguous linear memory buffers