Iterator Design Pattern in Java
This article explains Iterator design pattern in java with UML class diagram. It then takes an example scenario in java and explains it with class diagram and code.
Introduction
Iterator Design Pattern is a behavioral design pattern among the Gang Of Four(GOF) Design PatternsArticle on GOF Patterns & their types. Being a behavioral design pattern, the Iterator pattern deals with how objects of the designed system interact with each other.
What is Iterator Design Pattern Iterator design pattern implements the logic for sequential access of a collection of data outside of the collection(aka an aggregate) itself. This decouples the iteration logic from the collection implementation.
Defining an abstract interface for an iterator makes it possible to have multiple ways of iterating the same collection. Lets say we have a collection representing a binary tree. We can then have multiple concrete implementations of the same iterator abstraction accessing the elements in the tree using different traversal logic like in-order,pre-order and post-order. The binary tree collection remains the same but using Iterator pattern we access it in multiple ways without altering and/or directly accessing the binary tree implementation itself.
Scenarios in which Iterator Design Pattern can be used Given below are the scenarios in which an iterator pattern implementation is ideal for accessing elements of a collection-
Class Diagram for Iterator Design Pattern
Explanation of Iterator Design Pattern's Class Diagram
Code for the classes shown in Java Example's Class Diagram
OUTPUT of the above code
Explanation of Java Example's Class Diagram & Code
The Java class diagram above depicts Iterator Design pattern implemented for traversing a Sequence interface which has two concrete classes - ListSequence & LinkedListSequence. Lets quickly go through whats there in Java's example's class diagram & corresponding code -
Summary
In the above tutorial we understood what is Iterator design pattern and the main scenarios in which it is applicable. We then looked at the UML class diagram for Iterator Design Pattern & its explanation, a Java Use Case implementing Iterator pattern with its class diagram and code for the classes shown in the class diagram, followed by explanation of both the class diagram & code. This concludes the tutorial on Iterator design pattern.
What is Iterator Design Pattern Iterator design pattern implements the logic for sequential access of a collection of data outside of the collection(aka an aggregate) itself. This decouples the iteration logic from the collection implementation.
Defining an abstract interface for an iterator makes it possible to have multiple ways of iterating the same collection. Lets say we have a collection representing a binary tree. We can then have multiple concrete implementations of the same iterator abstraction accessing the elements in the tree using different traversal logic like in-order,pre-order and post-order. The binary tree collection remains the same but using Iterator pattern we access it in multiple ways without altering and/or directly accessing the binary tree implementation itself.
Scenarios in which Iterator Design Pattern can be used Given below are the scenarios in which an iterator pattern implementation is ideal for accessing elements of a collection-
- Collection's internal implementation is to be hidden: When the collection to be iterated does not want to expose its internal structure/representation to all the accessors of its data. The knowledge of internal structure of the collection is then restricted to the iterator. The accessors directly do not access the collection.
- Multiple ways of traversing the collection are possible: As explained with the binary tree example above, multiple implementations of the iterator abstraction enable the accessors to traverse the collection in multiple ways.
- Iteration logic is decoupled from the collection's internal structure: This scenario refers to polymorphic iteration. Lets say the collection being accessed itself has an abstract interface which multiple types of collection implementations possible.
For our binary tree example lets say we have two variations of binary trees - balanced and AVL. We define a common interface named BinaryTree and then define two concrete implementations of BinaryTree named - BalancedBinaryTree & AVLBinaryTree. The iterator abstraction would then use the interface BinaryTree to access the concrete binary tree collection implementation which could be any of the two types. This is an example of polymorphic iteration.
- Aggregate is the base interface for the family of collections which are to be iterated.It defines the method createIterator() in which all aggregates instantiate and return their own iterators.
- ConcreteAggregate is the concrete subclass of aggregate. It overrides createIterator().
- Iterator is the base interface for the family of iterators which traverse over the Aggregate family of collections.
- Iterator has four methods -
- firstItem() resets the iterator to point to the first item in the collection.
- nextItem() moves the iterator forward to next item in the collection.
- isOver() returns a boolean indicating whether the collection is fully traversed or not.
- getCurrentItem() returns the item to which the iterator is currently pointing.
- ConcreteIterator is a concrete instance of Iterator interface. It stores internally the concrete aggregate's instance over which it has to iterate. This concrete aggregate instance is returned to it by the concrete aggregate itself.
Interface Sequence<T>
public interface Sequence<T> {
public SequenceIterator<T> createSeqIterator();
}
Interface SequenceIterator<T>
public interface SequenceIterator<T> {
public T getCurrentItem();
public boolean isOver();
public void nextItem();
public void firstItem();
}
Class ListSequence<T>
import java.util.ArrayList;
import java.util.List;
public class ListSequence<T> implements Sequence<T> {
private List<T> list=new ArrayList<T>();
@Override
public SequenceIterator<T> createSeqIterator() {
return new ListSequenceIterator<T>(this);
}
//setter & getter for private list variable
}
Class LinkedListSequence<T>
import java.util.ArrayList;
import java.util.List;
public class LinkedListSequence<T> implements Sequence<T> {
private List<T> list=new ArrayList<T>();
@Override
public LinkedListSequenceIterator<T> createSeqIterator() {
return new LinkedListSequenceIterator<T>(this);
}
//setter & getter for private list variable
}
class ListSequenceIterator<T>
public class ListSequenceIterator<T> implements SequenceIterator<T>{
private ListSequence<T> list=null;
public ListSequenceIterator(ListSequence<T> list) {
super();
this.list = list;
}
private int currentItemNo=0;
@Override
public T getCurrentItem() {
return (this.list.getList().get(currentItemNo));
}
@Override
public boolean isOver() {
if(currentItemNo==list.getList().size()){
return true;
}else{
return false;
}
}
@Override
public void nextItem() {
this.currentItemNo++;
}
@Override
public void firstItem() {
this.currentItemNo=0;
}
}
Class LinkedListSequenceIterator<T>
public class LinkedListSequenceIterator<T> implements SequenceIterator<T>{
private LinkedListSequence<T> list=null;
public LinkedListSequenceIterator(LinkedListSequence<T> list) {
super();
this.list = list;
}
private int currentItemNo=0;
//Rest of the code for this class is same as ListSequenceIterator
//as LinkedList & ArrayList both implement java.util.List
}
Client.java with the main() method
import java.util.Arrays;
public <span class="jb-highlight-lightgreen">class Client</span> {
public static void main(String[] args) {
//Iterating over a list sequence
ListSequence<Integer> listSequence = new ListSequence<Integer>();
listSequence.setList(Arrays.asList(12,20,28,36));
ListSequenceIterator<Integer> listSeqIterator= (ListSequenceIterator<Integer>)listSequence.createSeqIterator();
System.out.println("Printing listSequence's items");
printIteratorElements(listSeqIterator);
//Iterating over a list sequence
LinkedListSequence<Integer> linkedListSequence = new LinkedListSequence<Integer>();
linkedListSequence.setList(Arrays.asList(111,122,108,242));
LinkedListSequenceIterator<Integer> linkedListSeqIterator=(LinkedListSequenceIterator<Integer>)linkedListSequence.createSeqIterator();
System.out.println("Printing linkedListSequence's items");
printIteratorElements(linkedListSeqIterator);
}
private static void printIteratorElements(SequenceIterator<?> listSeqIterator){
while(listSeqIterator.isOver()==false){
System.out.println("item->"+listSeqIterator.getCurrentItem());
listSeqIterator.nextItem();
}
}
}
Printing listSequence's items item->12 item->20 item->28 item->36 Printing linkedListSequence's items item->111 item->122 item->108 item->242
Sequence
is the base interface for a collection-type of data structure.ListSequence
&LinkedListSequence
are concrete implementations ofSequence
. They hold their data in instance ofjava.util.ArrayList
andjava.util.LinkedList
respectively.SequenceIterator
is the base interface for family of iterators capable of traversing Sequences.ListSequenceIterator
&LinkedListSequenceIterator
are concrete subclasses ofSequenceIterator
responsible for iterating overListSequence
&LinkedListSequence
respectively.Client
creates an instance ofListSequence
, initializes it with anArrayList
with few values.Client
then creates an instance ofListIterator
from it. Similary,Client
creates instances ofLinkedListSequence
, populates it with aLinkedList
instance & creates an instance ofLinkedListIterator
.Client
uses a generic method calledprintIteratorElements()
which takes as input param allSequenceIterator
s and prints their contents.
Gang of Four (GOF) Design Patterns on JavaBrahman
Creational Patterns: Factory method PatternFactory Method Design Pattern in Java Builder PatternBuilder Design Pattern in Java Prototype PatternPrototype Design Pattern in Java
Behavioral Patterns: Chain of Responsibility PatternChain of Responsibility Design Pattern in Java Observer PatternObserver Design Pattern in Java Iterator PatternIterator Design Pattern in Java State PatternState Design Pattern in Java Memento PatternMemento Design Pattern in Java Visitor PatternVisitor Design Pattern in Java Strategy PatternStrategy Design Pattern in Java Template Method PatternTemplate Method Design Pattern in Java
Structural Patterns: Adapter PatternAdapter design pattern in Java Composite PatternComposite Design Pattern in Java Facade PatternFacade Design Pattern in Java Proxy Pattern Java Proxy Design Pattern in Java
Analysis of Patterns: Strategy vs State PatternStrategy Design Pattern versus State Design Pattern
Creational Patterns: Factory method PatternFactory Method Design Pattern in Java Builder PatternBuilder Design Pattern in Java Prototype PatternPrototype Design Pattern in Java
Behavioral Patterns: Chain of Responsibility PatternChain of Responsibility Design Pattern in Java Observer PatternObserver Design Pattern in Java Iterator PatternIterator Design Pattern in Java State PatternState Design Pattern in Java Memento PatternMemento Design Pattern in Java Visitor PatternVisitor Design Pattern in Java Strategy PatternStrategy Design Pattern in Java Template Method PatternTemplate Method Design Pattern in Java
Structural Patterns: Adapter PatternAdapter design pattern in Java Composite PatternComposite Design Pattern in Java Facade PatternFacade Design Pattern in Java Proxy Pattern Java Proxy Design Pattern in Java
Analysis of Patterns: Strategy vs State PatternStrategy Design Pattern versus State Design Pattern