Design Pattern

Iterator Pattern

Clean Java-only production-ready implementation.


Provide a way to access elements of an aggregate object sequentially without exposing its underlying representation.

// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A custom HR profiles directory enabling client traversal without exposing
// internal list implementations.
//
// WHERE THE ITERATOR FITS IN:
// ProfileIterator acts as the Iterator interface. ProfileCollection acts as
// the Aggregate collection exposing .createIterator().
// ────────────────────────────────────────────────────────────────────────────
import java.util.ArrayList;
import java.util.List;

interface Iterator<T> {
    boolean hasNext();
    T next();
}

// --- Custom collection ---
class BrowseHistory {
    private final List<String> urls = new ArrayList<>();

    public void push(String url) { urls.add(url); }

    public Iterator<String> createIterator() {
        return new ListIterator(urls);
    }

    // --- Concrete iterator ---
    private static class ListIterator implements Iterator<String> {
        private final List<String> urls;
        private int index = 0;

        ListIterator(List<String> urls) { this.urls = urls; }

        public boolean hasNext() { return index < urls.size(); }

        public String next() {
            if (!hasNext()) throw new java.util.NoSuchElementException();
            return urls.get(index++);
        }
    }
}

// --- Client ---
public class Main {
    public static void main(String[] args) {
        BrowseHistory history = new BrowseHistory();
        history.push("google.com");
        history.push("github.com");
        history.push("stackoverflow.com");

        Iterator<String> it = history.createIterator();
        while (it.hasNext()) {
            System.out.println("  " + it.next());
        }
    }
}