Search Knowledge

© 2026 LIBREUNI PROJECT

Software Engineering & OOAD / Design Patterns

Template Method & Iterator Patterns

Template Method & Iterator Patterns

Our final look at Behavioral Patterns covers two patterns that optimize how we structure algorithms and how we traverse data. Both patterns are heavily used in modern frameworks and standard libraries.


1. The Template Method Pattern

The Problem

Imagine you are writing a data mining application that extracts information from various document formats (PDF, DOC, CSV). Most of the steps are identical: open the file, extract data, parse data, analyze data, and close the file. However, the extraction and parsing logic differs for each format. If you duplicate the skeleton logic in every class, you’ll have a maintenance nightmare.

The Solution

The Template Method pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

The base class defines “hooks” or abstract methods that subclasses must implement, while the “template method” itself is usually final (in Java) or intended not to be overridden.

Java Implementation

abstract class DataMiner {
    // 1. The Template Method
    public final void mine(String path) {
        openFile(path);
        extractData();
        parseData();
        analyzeData();
        closeFile();
    }

    // 2. Concrete steps (same for all)
    private void analyzeData() { System.out.println("Analyzing data..."); }
    private void closeFile() { System.out.println("Closing file."); }

    // 3. Abstract steps (different for each)
    protected abstract void openFile(String path);
    protected abstract void extractData();
    protected abstract void parseData();
}

class PdfDataMiner extends DataMiner {
    protected void openFile(String path) { System.out.println("Opening PDF: " + path); }
    protected void extractData() { System.out.println("Extracting text from PDF..."); }
    protected void parseData() { System.out.println("Parsing PDF structure..."); }
}

Pros and Cons

  • Pros: Promotes code reuse by pulling shared logic into a superclass. Provides a rigid structure that subclasses can’t easily break.
  • Cons: Some clients might be limited by the provided skeleton. Violates the Liskov Substitution Principle if you’re not careful.

2. The Iterator Pattern

The Problem

A collection is just a container for a group of objects. It could be a List, a Stack, a Tree, or a Graph. If you want to traverse these collections, you need various methods. A Tree requires Depth-First or Breadth-First traversal. If the client code has to handle these different traversal logics, it becomes tightly coupled to the internal structure of the collection.

The Solution

The Iterator pattern provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation (List, Stack, Tree, etc.).

By implementing an Iterator interface, different collections can provide their own iterators, allowing the client to traverse them using the same consistent API (e.g., hasNext() and next()).

Python Example

from collections.abc import Iterable, Iterator

# Concrete Iterator
class AlphabeticalOrderIterator(Iterator):
    def __init__(self, collection, reverse: bool = False):
        self._collection = collection
        self._reverse = reverse
        self._position = -1 if reverse else 0

    def __next__(self):
        try:
            value = self._collection[self._position]
            self._position += -1 if self._reverse else 1
        except IndexError:
            raise StopIteration()
        return value

# Concrete Collection
class WordCollection(Iterable):
    def __init__(self, collection = []):
        self._collection = collection

    def __iter__(self) -> AlphabeticalOrderIterator:
        return AlphabeticalOrderIterator(self._collection)

    def get_reverse_iterator(self) -> AlphabeticalOrderIterator:
        return AlphabeticalOrderIterator(self._collection, True)

    def add_item(self, item):
        self._collection.append(item)

# Usage
words = WordCollection()
words.add_item("First")
words.add_item("Second")
words.add_item("Third")

print("Straight traversal:")
for item in words:
    print(item)

print("\nReverse traversal:")
for item in words.get_reverse_iterator():
    print(item)

Iterator in Modern Languages

Most modern languages (Java, Python, C#, JavaScript) have built-in support for the Iterator pattern. In Java, it’s the Iterator<T> interface and foreach loops. In Python, it’s the __iter__ and __next__ methods.

Pros and Cons

  • Pros: Clean client code (no complex loops). Multiple traversals can happen simultaneously. You can delay traversal (lazy loading).
  • Cons: Can be overkill for simple collections. Might be slightly less efficient than a direct loop for some data structures.