Iterator Pattern

Iterator pattern is a behavioral design pattern in which an iterator is used to traverse a container and access the container's elements.

Iterator pattern decouples algorithms to manipulate data from it's containers. Note: in some cases, algorithms are necessarily container-specific and in that case, algorithms cannot be decoupled from.

The intent of this pattern, according to Design Patterns by Gamma et al, is to

  • Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
  • Promote to "full object status" the traversal of a collection.

This pattern is useful when you need access to elements in a set without access to the entire representation. Also, iterator would be a good choice when you need a uniform traversal interface, and multiple traversals may happen across elements.

 

Structure

The Client uses Aggregate interface directly. But access to the ConcreteAggregate’s elements is encapsulated behind the additional level of abstraction called Iterator. Each ConcreteAggregate class knows which Iterator derived class to create and return. After that, the Client relies on the interface defined in the Iterator base class.

The structure of the composite pattern is shown below:

iterator pattern example

Figure: Iterator Pattern Structure

Participants

 The classes and objects participating in this pattern are:

  • Iterator

     

    • defines an interface for accessing and traversing elements.
  • ConcreteIterator

     

    • implements the Iterator interface.
    • keeps track of the current position in the traversal of the aggregate.
  • Aggregate

     

    • defines an interface for creating an Iterator object
  • ConcreteAggregate

     

    • implements the Iterator creation interface to return an instance of the proper ConcreteIterator

 

Example

Consider a system which iterates over the collection of book names and prints them.

The UML class class diagram below describes the system.

iterator pattern example

Figure: Iterator Pattern Example

 

Java Implementation

Let us first create an interface for Iterator.

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

Also, let us add Aggregate interface.

/**
 * aggregate
 */
public interface Container {
    Iterator getIterator();
}

The implemented aggregate class is:

/**
 * concrete aggregate
 */
public class BookCollection implements Container {
    private String[] book = {"Programming C++" , "Learn Java" ,"ANSI C" , "AngularJS"};
    @Override
    public Iterator getIterator() {
        return new BookIterator();
    }

    public String[] getBooks(){
        return book;
    }
}

Similarly, cocrete iterator is,

/**
 * Concrete iterator
 */
public class BookIterator implements Iterator {
    private BookCollection collection = new BookCollection();
    private String[] books = collection.getBooks();
    private int index =0 ;

    @Override
    public boolean hasNext() {
        return index < books.length;
    }

    @Override
    public Object next() {
        return this.hasNext() ? books[index++]:null;
    }
}

Now, let us create a client that uses this pattern.

/**
 * client
 */
public class Application {
    public static void main(String[] args) {
        Container collection = new BookCollection();

        for (Iterator i = collection.getIterator();i.hasNext();){
            String book = (String)i.next();
            System.out.println(book);
        }
    }
}

The output of the program is:

Programming C++
Learn Java
ANSI C
AngularJS

The output makes it clear that the iterator object goes though each element in a collection.

Also, this pattern makes your code much more reasonable, getting rid of the typical for loop syntax across sections of your codebase.

Command Pattern
State Pattern