The Iterator design pattern is a behavioral design pattern that provides a way to access the elements of an aggregate object (like a list) sequentially without exposing its underlying representation. It defines a separate object, called an iterator, which encapsulates the details of traversing the elements of the aggregate, allowing the aggregate to change its internal structure without affecting the way its elements are accessed.
- Iterator Pattern is a relatively simple and frequently used design pattern. There are a lot of data structures/collections available in every language.
- Each collection must provide an iterator that lets it iterate through its objects. However, while doing so it should make sure that it does not expose its implementation.

Components
The Iterator design pattern consists of several components:

1. Iterator Interface/Abstract Class: Defines the interface for accessing and traversing elements in the collection. It typically includes methods like hasNext(), next(), and optionally remove().
2. Concrete Iterator: Implements the Iterator interface and maintains the current position in the traversal of the aggregate. It provides the actual implementation for the traversal operations defined in the Iterator interface.
3. Aggregate Interface/Abstract Class: Defines the interface for creating an Iterator object. It typically includes a method like createIterator() that returns an Iterator object for the collection.
4. Concrete Aggregate: Implements the Aggregate interface and represents the collection of objects. It provides the implementation for creating an Iterator object that can traverse its elements.
Working
This pattern works by providing a separate object to traverse elements of a collection sequentially.
- The collection provides an iterator object
- The iterator keeps track of the current position
- Methods like hasNext() and next() are used to move through elements
- The internal structure of the collection remains hidden
Uses
The Iterator pattern is commonly used in the following scenarios.
- Traversing lists, arrays, or collections
- Accessing data structures without exposing their implementation
- Implementing navigation features (next/previous)
- Supporting multiple simultaneous traversals
Example
Problem Statement:
Let's say we have a collection of employees in a company, and we want to iterate over the employees to calculate their total salary. However, the employees are stored in different types of collections (arrays, lists, etc.), and we want to iterate over them without exposing the underlying collection types.

Benefit of using the Iterator Pattern
The Iterator pattern allows us to access the elements of a collection sequentially without exposing its underlying representation. It provides a way to iterate over a collection regardless of its internal structure.
Implementation of above Example
Let’s break down into the component wise code:
1. Iterator Interface
Defines the methods for accessing and traversing the collection.
template <typename T>\nclass Iterator {\npublic:\n virtual bool hasNext() = 0;\n virtual T next() = 0;\n};
interface Iterator<T> {
boolean hasNext();
T next();
}
from abc import ABC, abstractmethod\n\nclass Iterator(ABC):\n @abstractmethod\n def hasNext(self):\n pass\n @abstractmethod\n def next(self):\n pass
// JavaScript doesn't have interfaces, but we can mimic one using a class with abstract methods\nclass Iterator {
hasNext() {
throw new Error('Method hasNext() must be implemented.');
}
next() {
throw new Error('Method next() must be implemented.');
}
}
2. Aggregate Interface
Defines the method for creating an iterator.
/*
Cpp implementation of Aggregate interface
*/
#include <vector>
#include <iterator>
template <typename T>
class Aggregate {
private:
std::vector<T> collection;
public:
Aggregate(std::vector<T> col) : collection(col) {}
class Iterator {
private:
typename std::vector<T>::iterator position;
public:
Iterator(typename std::vector<T>::iterator pos) : position(pos) {}
T operator*() { return *position; }
Iterator& operator++() { ++position; return *this; }
bool operator!=(const Iterator& other) const { return position!= other.position; }
};
Iterator createIterator() { return Iterator(collection.begin()); }
};
interface Aggregate<T> {
Iterator<T> createIterator();
}
"""
Python implementation of Aggregate interface
"""
class Aggregate:\n def __init__(self, collection):\n self.collection = collection\n\n class Iterator:\n def __init__(self, collection):\n self.collection = collection\n self.position = 0\n\n def __iter__(self):\n return self\n\n def __next__(self):\n if self.position < len(self.collection):\n result = self.collection[self.position]\n self.position += 1\n return result\n else:\n raise StopIteration\n\n def create_iterator(self):\n return self.Iterator(self.collection)
"""
JavaScript implementation of Aggregate interface
"""
class Aggregate {\n constructor(collection) {\n this.collection = collection;\n }\n\n createIterator() {\n return new Iterator(this.collection);\n }\n}\n\nclass Iterator {\n constructor(collection) {\n this.collection = collection;\n this.position = 0;\n }\n\n next() {\n if (this.position < this.collection.length) {\n const result = this.collection[this.position];\n this.position += 1;\n return { value: result, done: false };\n }\n return { done: true };\n }\n}\n
3. Concrete Iterator
Implements the Iterator interface and provides the actual iteration logic.
#include <vector>
#include <stdexcept>
class Employee {
public:
// Employee class definition
};
class EmployeeIterator {
private:
int currentIndex = 0;
std::vector<Employee> employees;
public:
EmployeeIterator(std::vector<Employee> employees) : employees(employees) {}
bool hasNext() {
return currentIndex < employees.size();
}
Employee next() {
if (!hasNext()) {
throw std::out_of_range("No such element");
}
return employees[currentIndex++];
}
};
class EmployeeIterator implements Iterator<Employee> {
private int currentIndex = 0;
private List<Employee> employees;
public EmployeeIterator(List<Employee> employees) {
this.employees = employees;
}
@Override
public boolean hasNext() {
return currentIndex < employees.size();
}
@Override
public Employee next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return employees.get(currentIndex++);
}
}
class Employee:
# Employee class definition
pass
class EmployeeIterator:
def __init__(self, employees):
self.currentIndex = 0
self.employees = employees
def hasNext(self):
return self.currentIndex < len(self.employees)
def next(self):
if not self.hasNext():
raise StopIteration
employee = self.employees[self.currentIndex]
self.currentIndex += 1
return employee
class Employee {
// Employee class definition
}
class EmployeeIterator {
constructor(employees) {
this.currentIndex = 0;
this.employees = employees;
}
hasNext() {
return this.currentIndex < this.employees.length;
}
next() {
if (!this.hasNext()) {
throw new Error('No such element');
}
return this.employees[this.currentIndex++];
}
}
4. Concrete Aggregate
Implements the Aggregate interface and provides the method to create an iterator for the collection.
#include <vector>
#include <iterator>
class Employee; // Assume Employee class is defined elsewhere
class Company {
std::vector<Employee> employees;
public:
Company(std::vector<Employee> employees) : employees(employees) {}
// Assuming Aggregate and Iterator are defined elsewhere
class Iterator : public Iterator<Employee> {
// Implementation of Iterator
};
Iterator createIterator() {
return Iterator(employees);
}
};
class Company implements Aggregate<Employee> {
private List<Employee> employees;
public Company(List<Employee> employees) {
this.employees = employees;
}
@Override
public Iterator<Employee> createIterator() {
return new EmployeeIterator(employees);
}
}
from typing import List, Iterator
# Assume Employee class is defined elsewhere
class EmployeeIterator:
def __init__(self, employees: List['Employee']):
self._employees = employees
self._index = 0
def __iter__(self):
return self
def __next__(self):
if self._index < len(self._employees):
employee = self._employees[self._index]
self._index += 1
return employee
raise StopIteration
class Company:
def __init__(self, employees: List['Employee']):
self.employees = employees
def create_iterator(self) -> 'EmployeeIterator':
return EmployeeIterator(self.employees)
// Assume Employee class is defined elsewhere
class EmployeeIterator {
constructor(employees) {
this.employees = employees;
this.index = 0;
}
[Symbol.iterator]() {
return this;
}
next() {
if (this.index < this.employees.length) {
return { value: this.employees[this.index++], done: false };
}
return { done: true };
}
}
class Company {
constructor(employees) {
this.employees = employees;
}
createIterator() {
return new EmployeeIterator(this.employees);
}
}
Complete code for the above example
This code demonstrates how the Iterator pattern can be used to iterate over a collection of employees in a company, regardless of the internal storage of the employees. Below is the complete code for the above example:
#include <iostream>
#include <vector>
// Employee class
class Employee {
private:
std::string name;
double salary;
public:
Employee(std::string name, double salary) : name(name), salary(salary) {}
double getSalary() { return salary; }
};
// Iterator interface
template <typename T>
class Iterator {
public:
virtual bool hasNext() = 0;
virtual T next() = 0;
};
// Aggregate interface
template <typename T>
class Aggregate {
public:
virtual Iterator<T>* createIterator() = 0;
};
// Concrete Iterator
class EmployeeIterator : public Iterator<Employee> {
private:
int currentIndex = 0;
std::vector<Employee> employees;
public:
EmployeeIterator(std::vector<Employee> employees) : employees(employees) {}
bool hasNext() override {
return currentIndex < employees.size();
}
Employee next() override {
if (!hasNext()) {
throw std::out_of_range("No such element");
}
return employees[currentIndex++];
}
};
// Concrete Aggregate
class Company : public Aggregate<Employee> {
private:
std::vector<Employee> employees;
public:
Company(std::vector<Employee> employees) : employees(employees) {}
Iterator<Employee>* createIterator() override {
return new EmployeeIterator(employees);
}
};
// Main class
int main() {
std::vector<Employee> employees = { Employee("Alice", 50000), Employee("Bob", 60000), Employee("Charlie", 70000) };
Company company(employees);
Iterator<Employee>* iterator = company.createIterator();
double totalSalary = 0;
while (iterator->hasNext()) {
totalSalary += iterator->next().getSalary();
}
std::cout << "Total salary: " << totalSalary << std::endl;
return 0;
}
import java.util.*;
// Employee class
class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public double getSalary() {
return salary;
}
}
// Iterator interface
interface Iterator<T> {
boolean hasNext();
T next();
}
// Aggregate interface
interface Aggregate<T> {
Iterator<T> createIterator();
}
// Concrete Iterator
class EmployeeIterator implements Iterator<Employee> {
private int currentIndex = 0;
private List<Employee> employees;
public EmployeeIterator(List<Employee> employees) {
this.employees = employees;
}
@Override
public boolean hasNext() {
return currentIndex < employees.size();
}
@Override
public Employee next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return employees.get(currentIndex++);
}
}
// Concrete Aggregate
class Company implements Aggregate<Employee> {
private List<Employee> employees;
public Company(List<Employee> employees) {
this.employees = employees;
}
@Override
public Iterator<Employee> createIterator() {
return new EmployeeIterator(employees);
}
}
// Main class
public class Main {
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("Alice", 50000));
employees.add(new Employee("Bob", 60000));
employees.add(new Employee("Charlie", 70000));
Company company = new Company(employees);
Iterator<Employee> iterator = company.createIterator();
double totalSalary = 0;
while (iterator.hasNext()) {
totalSalary += iterator.next().getSalary();
}
System.out.println("Total salary: " + totalSalary);
}
}
# Employee class
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def get_salary(self):
return self.salary
# Iterator interface
from abc import ABC, abstractmethod
class Iterator(ABC):
@abstractmethod
def has_next(self):
pass
@abstractmethod
def next(self):
pass
# Aggregate interface
class Aggregate(ABC):
@abstractmethod
def create_iterator(self):
pass
# Concrete Iterator
class EmployeeIterator(Iterator):
def __init__(self, employees):
self.employees = employees
self.index = 0
def has_next(self):
return self.index < len(self.employees)
def next(self):
if not self.has_next():
raise StopIteration
employee = self.employees[self.index]
self.index += 1
return employee
# Concrete Aggregate
class Company(Aggregate):
def __init__(self, employees):
self.employees = employees
def create_iterator(self):
return EmployeeIterator(self.employees)
# Main class
if __name__ == "__main__":
employees = [Employee("Alice", 50000), Employee("Bob", 60000), Employee("Charlie", 70000)]
company = Company(employees)
iterator = company.create_iterator()
total_salary = 0
while iterator.has_next():
total_salary += iterator.next().get_salary()
print(f'Total salary: {total_salary}')
class Employee {
constructor(name, salary) {
this.name = name;
this.salary = salary;
}
}
// Iterator interface
class Iterator {
constructor(collection) {
this.collection = collection;
this.currentIndex = 0;
}
hasNext() {
return this.currentIndex < this.collection.length;
}
next() {
if (!this.hasNext()) {
throw new Error('No such element');
}
return this.collection[this.currentIndex++];
}
}
// Aggregate interface
class Aggregate {
createIterator() {
return null;
}
}
// Concrete Iterator
class EmployeeIterator extends Iterator {
constructor(collection) {
super(collection);
}
}
// Concrete Aggregate
class Company extends Aggregate {
constructor(collection) {
super();
this.collection = collection;
}
createIterator() {
return new EmployeeIterator(this.collection);
}
}
// Main function
function main() {
const employees = [
new Employee("Alice", 50000),
new Employee("Bob", 60000),
new Employee("Charlie", 70000)
];
const company = new Company(employees);
const iterator = company.createIterator();
let totalSalary = 0;
while (iterator.hasNext()) {
totalSalary += iterator.next().salary;
}
console.log("Total salary: " + totalSalary);
}
main();
Output
Total salary: 180000.0
Real-Life Example
TV Remote Channel List:
When you press next or previous on a remote, you don’t know how channels are stored internally—you just iterate through them one by one.
Advantages
This pattern simplifies traversal of collections without exposing their internal structure.
- Provides a uniform way to access elements of a collection
- Hides the internal representation of the collection
- Supports multiple traversals at the same time
Disadvantages
Despite its usefulness, it has some drawbacks.
- Can increase the number of classes
- May add extra overhead for simple collections
- Can be unnecessary for languages with built-in iterators