# Iterator Pattern

The Iterator Pattern is a behavioral design pattern that lets you traverse elements of a collection without exposing its underlying representation (list, stack, tree, etc.).

## 1. The Core Concept

Collections are one of the most used data types in programming. However, storing data is only half the job; you also need to retrieve it.
*   **The Problem:** How do you traverse a complex data structure (like a Graph or Tree) sequentially? Depth-first? Breadth-first? Random?
*   **The Solution:** Extract the traversal behavior of a collection into a separate object called an **Iterator**.

The Iterator object encapsulates all the traversal details, such as the current position and how many elements are left.

## 2. Analogy: Touring a City

You plan to visit Rome.
*   **The Collection:** The city of Rome and its sights.
*   **Iterator 1:** A physical map (You walk randomly).
*   **Iterator 2:** A Google Maps walking route (Optimized for distance).
*   **Iterator 3:** A local tour guide (Optimized for history).

The city remains the same, but the way you traverse it changes depending on the "Iterator" you choose.

## 3. Example (TypeScript)

Most modern languages (JS, Python, Java) have built-in iterators (e.g., `for..of` loops). Here is how it works under the hood.

```typescript
// The Iterator Interface
interface Iterator<T> {
    current(): T;
    next(): T;
    key(): number;
    valid(): boolean;
    rewind(): void;
}

// The Aggregator Interface
interface Aggregator {
    getIterator(): Iterator<string>;
}

// Concrete Iterator
class AlphabeticalOrderIterator implements Iterator<string> {
    private collection: WordsCollection;
    private position: number = 0;
    private reverse: boolean = false;

    constructor(collection: WordsCollection, reverse: boolean = false) {
        this.collection = collection;
        this.reverse = reverse;

        if (reverse) {
            this.position = collection.getCount() - 1;
        }
    }

    public rewind() {
        this.position = this.reverse ?
            this.collection.getCount() - 1 :
            0;
    }

    public current(): string {
        return this.collection.getItems()[this.position];
    }

    public key(): number {
        return this.position;
    }

    public next(): string {
        const item = this.collection.getItems()[this.position];
        this.position += this.reverse ? -1 : 1;
        return item;
    }

    public valid(): boolean {
        if (this.reverse) {
            return this.position >= 0;
        }
        return this.position < this.collection.getCount();
    }
}

// Concrete Collection
class WordsCollection implements Aggregator {
    private items: string[] = [];

    public getItems(): string[] {
        return this.items;
    }

    public getCount(): number {
        return this.items.length;
    }

    public addItem(item: string): void {
        this.items.push(item);
    }

    public getIterator(): Iterator<string> {
        return new AlphabeticalOrderIterator(this);
    }

    public getReverseIterator(): Iterator<string> {
        return new AlphabeticalOrderIterator(this, true);
    }
}

// Usage
const collection = new WordsCollection();
collection.addItem("First");
collection.addItem("Second");
collection.addItem("Third");

const iterator = collection.getIterator();

console.log("Straight traversal:");
while (iterator.valid()) {
    console.log(iterator.next());
}
// Output: First, Second, Third

console.log("\nReverse traversal:");
const reverseIterator = collection.getReverseIterator();
while (reverseIterator.valid()) {
    console.log(reverseIterator.next());
}
// Output: Third, Second, First
```

## 4. Pros and Cons

| Pros | Cons |
| :--- | :--- |
| **SRP:** Extracts bulky traversal algorithms into separate classes. | **Overkill:** If your app only works with simple lists, using an iterator is overkill compared to a simple `for` loop. |
| **OCP:** You can implement new types of collections and iterators without breaking existing code. | **Efficiency:** Using a specialized iterator might be less efficient than direct traversal for some specialized collections. |
| **Parallel Iteration:** You can iterate over the same collection in parallel because each iterator object contains its own iteration state. | |

## 5. Generators (Yield)

Many modern languages (Python, JavaScript, C#) support **Generators**, which provide a syntactic shortcut for creating iterators. Instead of building a class with `next()` and maintaining state manually, you write a function that uses the `yield` keyword.

*   **Yield:** When `yield` is called, the function pauses execution and returns the value. When `next()` is called again, the function resumes exactly where it left off.

### Example (JavaScript/TypeScript)

```javascript
function* numberGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = numberGenerator(); // Returns an Iterator
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
```

[[programming/design-patterns]]
[[programming/object-oriented-programming]]