You have an algorithm with a fixed sequence of steps, but some steps vary across implementations. Template Method puts the invariant skeleton in the base class and allows subclasses to override specific steps.
// ─── EXAMPLE 1 ──────────────────────────────────────────────────────────────
// WHAT WE ARE IMPLEMENTING:
// A continuous software delivery compiler specifying strict testing,
// building, and deployment pipelines.
//
// WHERE THE TEMPLATE METHOD FITS IN:
// BuildPipeline is the Abstract Class defining the template method
// runPipeline(). JavaBuildPipeline represents a Concrete Class customizing
// compiling.
// ────────────────────────────────────────────────────────────────────────────
abstract class DataProcessor {
// Template method — defines the skeleton
public final void process(String data) {
System.out.println("\n=== Processing " + getProcessorName() + " ===");
String parsed = parse(data);
boolean valid = validate(parsed);
if (!valid) {
System.out.println(" Validation failed — aborting");
onError(data);
return;
}
save(parsed);
notifyComplete(parsed);
}
// Steps subclasses must implement
protected abstract String getProcessorName();
protected abstract String parse(String data);
protected abstract boolean validate(String data);
protected abstract void save(String data);
// Hook — optional override
protected void onError(String data) {
System.out.println(" [Default] Logged error");
}
// Hook — optional override
protected void notifyComplete(String data) {
System.out.println(" [Default] Notification sent");
}
}
class CsvProcessor extends DataProcessor {
protected String getProcessorName() { return "CSV"; }
protected String parse(String data) { return data.replace(",", " | "); }
protected boolean validate(String data) { return data != null && !data.isEmpty(); }
protected void save(String data) { System.out.println(" [CSV] Saved: " + data); }
}
class JsonProcessor extends DataProcessor {
protected String getProcessorName() { return "JSON"; }
protected String parse(String data) { return "[Parsed JSON]: " + data; }
protected boolean validate(String data) { return data != null && data.startsWith("{"); }
protected void save(String data) { System.out.println(" [JSON] Stored: " + data); }
protected void notifyComplete(String data) { System.out.println(" [JSON] Published to event bus"); }
}
public class Main {
public static void main(String[] args) {
DataProcessor csv = new CsvProcessor();
csv.process("a,b,c");
DataProcessor json = new JsonProcessor();
json.process("{\"key\": \"value\"}");
json.process("invalid"); // Validation fails
}
}