The Template Method Pattern: Define the Skeleton, Let Subclasses Fill the Gaps

2026-05-05

You've written this code three times: same five steps, same order, but step three differs each time. You copy-paste, change the middle, and now you have three near-identical functions that drift apart over the next two years. The Template Method pattern fixes this by defining the algorithm's skeleton in a base class and letting subclasses override only the steps that vary.

The pattern has two ingredients:

Real-world example: a data import pipeline. Every importer does the same dance: open a source, validate the schema, transform rows, write to the warehouse, emit metrics. Only the source-opening and transformation logic differ between CSV, Parquet, and a vendor's REST API.

abstract class Importer {
  // Template method — the skeleton, locked down.
  final void run() {
    var raw = openSource();
    validate(raw);
    var rows = transform(raw);
    write(rows);
    emitMetrics(rows.size());
  }

  protected abstract Source openSource();
  protected abstract List<Row> transform(Source s);

  // Default hooks — override only if needed.
  protected void validate(Source s) { /* sane default */ }
}

Now CsvImporter and ParquetImporter each implement two methods instead of duplicating fifty lines. When you add OpenTelemetry tracing to run(), every importer gets it for free.

Rule of thumb: the 80/20 split. If 80% of your algorithm is identical across variants and 20% varies in predictable spots, Template Method pays off. If the variation is more like 50/50, or the steps differ in order rather than content, reach for Strategy or Chain of Responsibility instead.

Watch out for these traps:

Template Method shines when the process is the contract and the steps are the negotiation. Use it for ETL jobs, request lifecycles, test fixtures, and report generators — anywhere the recipe is fixed but the ingredients vary.

See it in action: Check out Define Skeleton, Let Subclasses Fill Gaps ♟️ by RetiredDev to see this theory applied.
Key Takeaway: When multiple workflows share the same skeleton but differ in a few specific steps, lock the algorithm in a base class and let subclasses override only the variations.

All newsletters