Behavioral · DWG NO. 023

Template Method

Fix the overall steps of an algorithm in a base class, and let subclasses fill in just the steps that vary.

TypeBehavioral
ScopeClass hierarchy
ComplexityLow
Common inData import pipelines, test frameworks, report generation

The overall steps repeat, but one or two steps differ each time

Importing CSV, JSON, and XML files all follow the same shape — open file, parse, validate rows, save to database — but each format parses differently. Copy-pasting the whole pipeline per format duplicates the steps that are actually identical.

The base class owns the sequence

A base class defines a method that calls a fixed sequence of steps, some implemented directly, others left abstract. Subclasses override only the steps that differ; the order and the shared steps live in one place.

DataImporterimport()CsvImporterparse() onlyJsonImporterparse() only

Shared import pipeline, format-specific parsing

`import()` is defined once, in the base class. Each format subclass only implements `parse()`.

data-importer.js
class DataImporter {
  import(raw) {
    console.log("opening source");
    const rows = this.parse(raw);      // step that varies — implemented by subclass
    const valid = rows.filter((r) => this.validate(r));
    console.log(`saving ${valid.length} rows`);
    return valid;
  }
  validate(row) { return row != null; } // shared default, subclasses may override
  parse(raw) { throw new Error("parse() must be implemented"); }
}

class CsvImporter extends DataImporter {
  parse(raw) { return raw.split("\n").map((line) => line.split(",")); }
}

class JsonImporter extends DataImporter {
  parse(raw) { return JSON.parse(raw); }
}

new CsvImporter().import("a,1\nb,2");
new JsonImporter().import('[{"a":1},{"b":2}]');

Trade-offs