Iterator Design Pattern in Java

1. Definition

The Iterator Design Pattern provides a way to access the elements of a collection object sequentially without exposing its underlying representation. It decouples algorithms from containers.

2. Problem Statement

Imagine you have different types of collections (e.g., array, linked list, tree). How can you provide a unified way to access and traverse their elements without exposing their internal structures?

3. Solution

The Iterator pattern solves this by providing a generic interface for traversing elements. Each collection will have its specific iterator implementing this interface, encapsulating its traversal logic.

4. Real-World Use Cases

1. Navigating through pages of a book.

2. Scrolling through songs on a music player.

3. Iterating through different types of collections in software libraries.

5. Implementation Steps

1. Define an Iterator interface with methods: hasNext(), next(), etc.

2. Implement concrete iterators for each collection type.

3. Collections provide a method to return their iterator.

6. Implementation

// Iterator Interface
interface Iterator<T> {
    boolean hasNext();
    T next();
}
// Concrete Collection
class ConcreteCollection {
    private String items[] = {"item1", "item2", "item3", "item4"};

    public Iterator<String> getIterator() {
        return new ConcreteIterator();
    }

    private class ConcreteIterator implements Iterator<String> {
        int index;

        public boolean hasNext() {
            return index < items.length;
        }

        public String next() {
            if(this.hasNext()) {
                return items[index++];
            }
            return null;
        }
    }
}

// Client
public class IteratorPatternDemo {
    public static void main(String[] args) {
        ConcreteCollection collection = new ConcreteCollection();
        Iterator<String> iterator = collection.getIterator();

        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Output:

item1
item2
item3
item4

Explanation

In this example, ConcreteCollection is our collection that provides its specific iterator, ConcreteIterator. The IteratorPatternDemo client retrieves this iterator and traverses the collection without knowing its internal structure.

7. When to use?

Use the Iterator Pattern when:

1. You want to access an aggregate object's contents without exposing its internal representation.

2. You need to support multiple traversal variants of aggregate objects.

3. You want a uniform way to traverse different aggregate structures (polymorphic iteration).


Comments