The Goal

Standardize a multi-step process, but let child classes customize specific steps.

Imagine you are deploying containerized services. The overall pipeline (Build, Test, Deploy) is always the same, but the way you build or deploy changes depending on if it is a Java app or a React app.

  1. The Abstract Base Class (The Template)
public abstract class DeploymentPipeline {
    
    // The TEMPLATE METHOD: Marked final so the core pipeline cannot be altered
    
    public final void executePipeline() {
        build();
        test();
        deploy();
    }

    // Shared behavior
    private void test() {
        System.out.println("Running standard SonarQube security scan...");
    }

    // Steps that MUST be customized by subclasses
    protected abstract void build();
    protected abstract void deploy();
}
  1. Concrete Implementations
public class JavaMicroserviceDeployment extends DeploymentPipeline {
    @Override
    protected void build() {
        System.out.println("Building Java 21 app using Maven & Dockerfile...");
    }

    @Override
    protected void deploy() {
        System.out.println("Pushing image to AWS ECR and updating ECS service...");
    }
}

Notice how the executePipeline() method locks in the overarching workflow. The subclass just fills in the blanks.