Iterator matters when traversal should vary independently from the collection or aggregate being traversed.
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
What the pattern is trying to do
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
What force creates the need
Clients need traversal behavior, but they should not depend on the internals of how the aggregate stores or computes its elements.
How the pattern responds
Expose iteration through a dedicated traversal interface or object instead of leaking collection internals.
How the moving parts fit together
An aggregate creates an iterator that maintains traversal state while clients consume elements through a stable sequence-oriented API.
Java example in the Order Management domain
package org.javaomnibus.ecommerce.gof.behavioral;
public final class ShipmentBatch {
private final java.util.List shipments;
public ShipmentBatch(java.util.List shipments) {
this.shipments = shipments;
}
public java.util.Iterator iterator() {
return shipments.iterator();
}
}
Step by step
- Clients traverse shipments without needing to know the aggregate internals.
- The pattern is built deeply into Java collections, so it often appears in familiar form.
- Custom iterators still matter when traversal order or filtering belongs to the aggregate.
- Iterator separates access from representation.
Where this pattern helps
- When an aggregate needs controlled traversal without exposing its storage details
- When multiple traversal strategies or views may exist
When a simpler design is better
- When ordinary collection iteration is already sufficient
- When wrapping plain iteration adds no domain value
What this pattern costs
- Custom iterators can be unnecessary if built-in iteration already solves the problem
- Traversal abstractions add little value unless they protect or clarify something important
How this fits today
Iterator remains foundational in Java because the language and collections framework rely on it heavily, even if many teams do not name it explicitly.
Where teams get it wrong
Writing bespoke iterator layers around simple lists without domain-specific traversal needs usually adds noise instead of abstraction value.