Saturday, August 24, 2019

Iterator Design Pattern

Iterator design pattern provides us a way to access the elements in a collection sequentially without exposing internal implementation/representation details to the client.

Programming languages provide a wide variety of collections/aggregates for storing the objects. List, Set, Arrays, Maps etc are very commonly used aggregates used by programmers. We employ different  aggregates for different scenarios and use-cases. But traversing through these aggregates always remains a requirement and is a very basic need in any kind of software program.

As these basic aggregate classes vary in underlying data structures, hence ways of traversing them also varies. We can naively provide methods in aggregates to access the elements, but this can easily expose internal details. Moreover, client code would also need to deal differently with different aggregates even though their need is same(accessing elements sequentially) and hence their are huge chances of code duplication.

Iterator pattern provides a solution to these basic aggregates traversing problems. We basically do two things when we implement iterator pattern.

First, we move the responsibility of traversing the aggregate elements to another class called Iterator. An iterator provides an interface for clients which they can use to traverse the elements. All iterator implementations thus provide this interface.

Second, we make aggregates to provide a simple interface to enable users to get hold of the iterator. Aggregates just need to instantiate appropriate iterator and provide it to client.

These simple structural changes mean several benefits. Aggregate is now only concerned about its core responsibility of storing the elements, while it is now Iterator's responsibility to traverse the elements in the aggregate. It greatly simplifies aggregate interface and also helps in achieving S of SOLID principles. Aggregate just provides interface which clients use to get hold of the iterator. Aggregate has now just two uniform interfaces to deal with irrespective the type of aggregate.

Code structure


Code structure is relatively simple.


Aggregate implements a simple interface which clients invoke to get Iterator instance. Aggregate just needs to instantiate appropriate concrete iterator implementation. Iterator provides clients the ways to traverse though the aggregate elements.

Java Iterators


Java collection classes implement Iterable interface. It maps to Aggregate in aobve UML diagram. This interface has three methods, one of which needs to be implemented by the concrete class(other two have default implementations). This method is named 'iterator' and it returns an Iterator.

Iterator is a simple interface having three basic methods for traversing collection elements:

  • hasNext: returns true is iteration has more elements
  • next: returns next element in iteration
  • remove: removes last element visited
remove has also a default implementation of throwing UnsupportedOperationException. So if a collection class doesn't want to support this method and hence doesn't implement it, exception is thrown to let client know about it.

There are several concrete implementations of Iterator available, like ListIterator. Concrete collection classes instantiates appropriate iterator implementations and return it as implementation of 'iterator' method.

No comments:

Post a Comment