Design Pattern

Template Method Pattern

Clean Java-only production-ready implementation.


What Problem It Solves

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.

Template Method vs Strategy

AspectTemplate MethodStrategy
ScopeAlgorithm skeleton with fixed stepsEntire algorithm interchangeable
ControlBase class controls the sequenceContext delegates entire algorithm
VariationOverride specific stepsReplace entire algorithm
InheritanceYes (subclass overrides)No (composition)

Implementation

// โ”€โ”€โ”€ 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
    }
}

๐Ÿ’ฌReview

Help Us Improve

How helpful was this walkthrough?

Click a star to rate. We actively use this feedback to refine and update our system design content.

Placeholder
Optional but highly appreciated!

Discussion

Share your thoughts, ask questions, or help others.

Loading comments...