I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Design Patterns Uncovered: The Iterator Pattern

06.03.2010
| 23644 views |
  • submit to reddit

Today's pattern is the Iterator pattern which formalizes how we move through a collection of data in a particular class

Iterator in the Real World 

MP3 player control is a good example of an iterator. The user doesn't mind how to view their list of songs, once they get to see them somehow. In older mp3 players, this was done using simple forward and back buttons. With the iPod this changed to the wheel navigation concept. The iPhone moves this on further to use swipe movements. Nevertheless, the same idea is provided by all interfaces - a way to iterate through your music collection.

Design Patterns Refcard
For a great overview of the most popular design patterns, DZone's Design Patterns Refcard is the best place to start. 

The Iterator Pattern

The Iterator pattern is known as a behavioural pattern, as it's used to manage algorithms, relationships and responsibilities between objects.. The definition of Iterator as provided in the original Gang of Four book on Design Patterns states: 

Provides a way to access the elements of an aggregate object without exposing its underlying represenation.

Let's take a look at the diagram definition before we go into more detail.

The Aggregate defines an interface for the creation of the Iterator object. The ConcreteAggregate implements this interface, and returns an instance of the ConcreteIterator. The Iterator defines the interface for access and traversal of the elements, and the ConcreteIterator implements this interface while keeping track of the current position in the traversal of the Aggregate.

Using this pattern, you can build on the standard concept of iteration to define special iterators that only return specific elements in the data set.

Would I Use This Pattern?

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

It also makes you code much more reasonable, getting rid of the typical for loop syntax across sections of your codebase.

So How Does It Work In Java?

Java provides an implementation of the Iterator pattern, which provides next() and hasNext() methods. Creation of the iterator in Java is typically done through a method named iterator() in the container class.
The following example shows use of an iterator with a list : 

List<String> list = new ArrayList<String>();
//add strings

Iterator it = list.iterator();
while(it.hasNext())
{
String s = it.next();
}

Now let's go to an example where we create the constructs ourselves, with a remote control example.
First we'll create an iterator with the standard methods:

//Iterator interface 
public interface ChannelIterator
{

public boolean hasNext();

public void next();

public String currentItem();

}

Next we create the Aggregate interface, in this case a TV. 




//Aggregate interface
public interface TV
{
public Channel getIterator();
//other TV methods
}

The concrete implementation of the aggregator has the capability to create the iterator

//Concrete Aggregator
public class ConcreteTV
{
private ChannelIterator iterator;
private List<String> channels;

public ConcreteTV()
{
iterator = new ConcreteChannelIterator(channels);
}

public ChannelIterator getIterator()
{
return iterator;
}

}

Finally the iterator helps control how we navigate the data. 

//Concrete Iterator 
//Iterator interface
public interface ChannelIterator
{
private List<String> channels;

private int currentPos = 0;

public ChannelIterator(List<String> channels)
{
this.channels = channels;
}

public boolean hasNext()
{
if(currentPos + 1 < channels.size())
{
return true;
}
return false;
}

public void next()
{
currentPos++;
}

public String currentItem()
{
return channels.get(currentPos);
}

}

Of course this is a one-way remote control. We could implement back() and hasBack() methods to navigate backwards in our iterator. 

Watch Out for the Downsides

I don't see any disadvantages to this pattern. It's simple, widely used and provides more readable code. However, you may disagree - if so, please let me know in the comments section.

Other Articles in This Series
The Observer Pattern
The Adapter Pattern
The Facade Pattern
The Factory Method Pattern
The Abstract Factory Pattern
The Singleton Pattern
The Strategy Pattern
The Visitor Pattern

The Decorator Pattern
The Proxy Pattern
The Command Pattern
The Chain of Responsibility Pattern
The Interpreter Pattern

Next Up

We've only two patterns left, so the penultimate pattern in our series will be the State pattern.
Tags:

Comments

Shubhashish Bhowmik replied on Mon, 2011/02/28 - 11:29am

Just curious, please correct me if i m wrong, shouldn't the last listing of code would be for "ConcreteChannelIterator" rather than "ChannelItertor".

Jitendra Kumar replied on Sat, 2013/08/03 - 10:24am in response to: Shubhashish Bhowmik

R9 Shubhasish, I was thinking about the same.... need to correct.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.