Easy Tutorial
❮ Observer Pattern Mediator Pattern ❯

Iterator Pattern

The Iterator Pattern is a frequently used design pattern in Java and .NET programming environments. This pattern is used to sequentially access the elements of a collection object without needing to know the underlying representation of the collection object.

The Iterator Pattern is a behavioral pattern.

Introduction

Intent: Provide a way to access the elements of an aggregate object sequentially without exposing its internal representation.

Main Solution: Traversing the entire aggregate object in different ways.

When to Use: When traversing an aggregate object.

How to Solve: Assign the responsibility of traversing elements to the iterator rather than the aggregate object.

Key Code: Define interfaces: hasNext, next.

Example: Iterator in JAVA.

Advantages:

  1. It supports traversing an aggregate object in different ways.
  2. Iterators simplify the aggregate class.
  3. Multiple traversals can be performed on the same aggregate.
  4. In the Iterator Pattern, adding new aggregate and iterator classes is convenient, without modifying existing code.

Disadvantages: Since the Iterator Pattern separates the storage and traversal responsibilities, adding new aggregate classes requires adding new iterator classes, which increases the number of classes in pairs, thereby increasing the complexity of the system to some extent.

Usage Scenarios:

  1. Accessing the content of an aggregate object without exposing its internal representation.
  2. Providing multiple traversal methods for an aggregate object.
  3. Providing a unified interface for traversing different aggregate structures.

Notes: The Iterator Pattern separates the traversal behavior of the collection object, abstracting an iterator class to handle it, so that the internal structure of the collection is not exposed, yet the internal data of the collection can be accessed transparently by external code.

Implementation

We will create an Iterator interface that describes navigation methods and a Container interface that returns an iterator. The concrete class implementing the Container interface will be responsible for implementing the Iterator interface.

The IteratorPatternDemo, our demo class, uses the concrete class NamesRepository to print the Names stored in NamesRepository as a collection.

Step 1

Create interfaces:

Iterator.java

public interface Iterator {
   public boolean hasNext();
   public Object next();
}

Container.java

public interface Container {
   public Iterator getIterator();
}

Step 2

Create a concrete class that implements the Container interface. This class has an inner class NameIterator that implements the Iterator interface.

NameRepository.java

public class NameRepository implements Container {
   public String[] names = {"Robert", "John", "Julie", "Lora"};

   @Override
   public Iterator getIterator() {
      return new NameIterator();
   }

   private class NameIterator implements Iterator {

      int index;

      @Override
      public boolean hasNext() {
         if (index < names.length) {
            return true;
         }
         return false;
      }

      @Override
      public Object next() {
         if (this.hasNext()) {
            return names[index++];
         }
         return null;
      }
   }
}

Step 3

Use NameRepository to get the iterator and print the names.

IteratorPatternDemo.java

public class IteratorPatternDemo {

   public static void main(String[] args) {
      NameRepository namesRepository = new NameRepository();

      for (Iterator iter = namesRepository.getIterator(); iter.hasNext();) {
         String name = (String) iter.next();
         System.out.println("Name : " + name);
      }
   }
}

Step 4

Execute the program, output result:

Name : Robert
Name : John
Name : Julie
Name : Lora
❮ Observer Pattern Mediator Pattern ❯