In this article we are going to learn about Iterator design patter

  • What is Iterator?
  • What are the basic principles?
  • How we can implement?
  • where we can use it?

I have used Java in Eclipse for my code. As this pattern is already added in Java and DotNet frameworks, in example I will just show how to use it and in implementation I will show how we can implement that.

What is Iterator?

In OO design, some time we need to search inside a collection of objects.

Iterator design pattern provides us to traverse in aggregated objects sequentially. Think like as accessing all element in a collection, even if the collection may be made of different type of data structure(list, array, hash, tree etc).

In a single sentence, iterator allows us to traverse & access a container’s elements sequentially.

UML :

uml-iterator

Principles :

  • Provides a way to access of an aggregate object sequentially without exposing internal implementation.
  • Allows us to modify the collection implementation without making any changes outside of collection.

How to Implement Iterator?

As we know, iterator will let us traverse sequentially, it should have functions to start traversing , end traversing.

Extra functions , current item and completion of traversing are also can be added.

From UML, we may see first(), next(), isDOne(), currentItem() are described.

In java and Dot net, there are bunch of functions are added with iterators. So, to implement that, we need

  1. Interface describing iterator qualities.
  2. Iterator class, implementing iterator qualities.
  3. An interface that implement container behavior. That means it will have the iterator inside.
  4. A collection that contains the objects and implement the container behavior.

So, lets make a iterator for our example. (we will only make to show how it works but we will use predefine iterator in the example)

So, here is an IIterator


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

And Container that contains

public interface IContainer {
    public IIterator createIterator();
}

And container implemented my container that has its own private iterator (myiterator)

public class MyContainer implements IContainer{
    private String[] bookNames = {"Design Pattern", "OOAD", "JAVA","C#"};
    private int iteratorPosition=0;    
    public IIterator createIterator() {
        return new MyIterator();
    }
    private class MyIterator implements IIterator{
        public boolean hasNext() {
        if(iteratorPosition<bookNames.length){
            return true;
        }else
            return false;
        }
        public Object next() 
        {
            if(this.hasNext()){
                return bookNames[iteratorPosition++];
            }
            else
                return null;
            }
        }
}

Let’s see the example to know what iterator do and how to use it.

Example :

Suppose we are in a books store.

  • The book store has a manager who has all book list.
  • Books are divide into Types. Let assume , 3 type. Detective books, Adventure books, Science books.
  • Those three kind of books actually act as container.
  • And we will use Hash table, Array, and Array List to store books. And we use common iterator .
  • And, an additional class Book Manager who actually shows book info. And a client just calls manager.

So the interface is

public interface IBookIterator {
    public Iterator createIterator();
}

The Item, book class(to keep simple, I have only string)

public class Book {
    private String title; 
    public Book(String atitle){
        this.title=atitle;
    }
    public String getTitle() {
        return title;
    }
}

And three types those apply three different type collection to act as container.

public class Adventurebook implements IBookIterator{   
    Hashtable <Integer, Book> myAdventurebooks ;
    int hashkey = 0;
    public Adventurebook(){
        myAdventurebooks = new Hashtable<Integer, Book>();
        addBook(new Book("ShutterIsland"));
        addBook(new Book("RobinSonCruso"));
        addBook(new Book("PiretsOfCarriba"));
    }
    public void addBook(Book aBook) {
        myAdventurebooks.put(hashkey, aBook);
        hashkey++;
    }
    public Iterator createIterator() {       
        return myAdventurebooks.values().iterator();
    }
}
public class Detectivebooks implements IBookIterator{
    ArrayList<Book> myDetectivebooks ;
    public Detectivebooks(){
        myDetectivebooks = new ArrayList<Book>();
        addBook(new Book("Varoth Nattyom-Rana"));
        addBook(new Book("Jhamela-TinGoyenda"));
        addBook(new Book("PanchPandob"));
    }
    public void addBook(Book aBook) {
        myDetectivebooks.add(aBook);        
    }
    public Iterator createIterator() {        
        return myDetectivebooks.iterator();
    }
}
 public class ScienceBook implements IBookIterator{
    Book[] myScienceBook ;
    int index = 0;
    public ScienceBook(){
        myScienceBook = new Book[2];
        addBook(new Book("Encyclopodia"));
        addBook(new Book("SpaceShips"));
    }
    public void addBook(Book aBook) {
        myScienceBook[index] = aBook;
        index++;
    }
    public Iterator createIterator() {       
        return Arrays.asList(myScienceBook).iterator();//adding iterator in array as list
    }
}

So, now the Manager class who will call those iterators to view all data.

public class BookManager {
    Detectivebooks detectiveCollection; 
    ScienceBook scienceCollection;
    Adventurebook adventureCollection;
    public BookManager(){    
        detectiveCollection= new Detectivebooks();
        scienceCollection= new ScienceBook();
        adventureCollection = new Adventurebook();
    }
    public void showAllBooks(){        
        System.out.println("Adventure books : ");
        printBooks(adventureCollection.createIterator());
        System.out.println("Science books : ");
        printBooks(scienceCollection.createIterator());
        System.out.println("Detective books : ");
        printBooks(detectiveCollection.createIterator());
    }
    private void printBooks(Iterator iterator){
        while(iterator.hasNext()){
            Book aBook = (Book)iterator.next();
            System.out.println("This is Book Name "+ aBook.getTitle());
        }
    }
}

And lastly, the client who only calls manager.

public class Client {
    public static void main(String[] args) {
        new BookManager().showAllBooks();
    }
}

Java Example :

  1. You may find the implementing project but it dies not have client
  2. Example project contains console output.

Usages :

  • To access different type of object collections without exposing the collection.
  • In situation when we need multiple simultaneous traversals of a collection.
  • When we need to provide a common interface to access/traverse different collections.