Template Design Pattern

In Template design pattern, we define the steps to execute an algorithm in a template method of an abstract base class without implementing some steps of the algorithm. It may contain the default implementation of the steps of algorithm that might be common for all or some of the subclasses. Its subclasses can override the specific steps of the algorithm as per requirement of subclasses but the algorithm execution sequence will be in the same way as defined by an abstract base class.

Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. In simple words, the template methods of the abstract base class declares algorithm with abstract placeholder methods and derived classes implement the placeholder methods. Template pattern comes under behavior design pattern category.

For Example:
To preparing a pizza we need to execute following three steps in sequence
  • Step 1. Prepare pizza base.
  • Step 2. Add toppings on pizza.
  • Step 3. Bake pizza in oven.
Above mentioned sequence of steps are same for preparation of all type of pizza however the execution of each step depends on specific pizza type. Suppose, we want to prepare one "veg pizza" and one "chicken pizza". Although, the steps of pizza preparation remians the same for both pizza but the specific details of second steps will change because we need to add different toppings for these two pizza types.

In this example, template method of base class "Pizza" will contain the sequential steps of pizza prepatation where as subclasses for "veg pizza" and "chicken pizza" pizza type will contain specific implementations of second step.

Structure of the Template Design Pattern

The Template Design Pattern consists of the following components:
  • AbstractClass (Template) : This conceptual blueprint outlines the template method, constituting the framework of the algorithm. It might encompass additional methods, some of which are abstract, while others possess default implementations.

  • ConcreteClass (ConcreteTemplate) : This specific blueprint serves as a subclass of the conceptual blueprint, offering tangible implementations for the abstract methods specified in the abstract blueprint. It tailors or overrides particular steps of the algorithm.

Benefits of the Template Design Pattern

The Template design approach provides several benefits that contribute to the development of adaptable and sustainable software systems:
  • Code Reusability : The Template Approach fosters code reuse by encapsulating the common steps of an algorithm within a Template method. Subsequent use by subclasses enables the reuse of the Template method, with the provision for specific implementations to accommodate variations.

  • Streamlined Maintenance : Maintenance tasks are streamlined since alterations to the common steps are consolidated in a single location—the Template method. Modifications to the algorithm no longer necessitate updates to each individual subclass, mitigating the risk of errors.

  • Uniformity Across Subclasses : This approach advocates for uniformity in algorithm implementation across diverse subclasses. The Template method defines the standardized sequence of steps, ensuring a consistent approach to problem-solving.

  • Facilitation of Code Extensibility : Subclasses can extend the capabilities of the Template method by supplying specific implementations for abstract methods. This extensibility permits the addition of new steps or variations without impacting existing code.

  • Efficient Code Organization : The Template Approach encourages efficient code organization by segregating the common steps of an algorithm from specific variations. This demarcation enhances modularity and simplifies code management.

  • Support for Algorithm Evolution : The approach supports the gradual evolution of algorithms over time. In response to emerging requirements, developers can introduce modifications to the Template method or incorporate new variations in subclasses without disrupting existing code.

  • Flexibility in Design : Design flexibility is heightened as developers can fashion new subclasses with distinct implementations while adhering to the established Template structure. This flexibility proves valuable in scenarios requiring multiple variations of an algorithm.
Leveraging these advantages, the Template Approach becomes an invaluable instrument for crafting reusable and sustainable software components. Its capacity to delineate a common Template method and accommodate variations through subclasses deems it suitable for scenarios where a family of algorithms shares a common structure.

Implementation of Template Design Pattern

We will create an abstract class called Pizza containing a template method preparePizza which define the generic sequence of steps to prepare a pizza. Each step of pizza preparation process is defined as an abstract method which acts as place holder. Each subclass(VegPizza and ChickenPizza) will have specific implemetation of each step for pizza preparation as required for that pizza type. Template Design Pattern UML Diagram Pizza.java
Abstract class Pizza contains template method preparePizza which defines the algorithn to prepare pizza as abstract methods.
public abstract class Pizza {
    abstract void preparePizzaBase();
    abstract void addToppings();
    abstract void bakePizza();

    //Template method
    public final void preparePizza(){
        // Prepare Pizza Base
        preparePizzaBase();
        // Add Toppings
        addToppings();
        // Bake Pizza
        bakePizza();
    }
}

VegPizza.java
VegPizza is a concrete class extending abstract class Pizza. It implements abstract methods as per the requirement to prepare a veg pizza.
public class VegPizza extends Pizza {
    @Override
    void preparePizzaBase() {
        System.out.println("Prepairing pizza base for Veg Pizza");
    }

    @Override
    void addToppings() {
        System.out.println("Adding toppings for Veg Pizza");
    }

    @Override
    void bakePizza() {
        System.out.println("Baking Veg Pizza");
    }
}

ChickenPizza.java
ChickenPizza is a concrete class extending abstract class Pizza. It implements abstract methods as per the requirement to prepare a chicken pizza.
public class ChickenPizza extends Pizza {
    @Override
    void preparePizzaBase() {
        System.out.println("Prepairing pizza base for Chicken Pizza");
    }

    @Override
    void addToppings() {
        System.out.println("Adding toppings for Chicken Pizza");
    }

    @Override
    void bakePizza() {
        System.out.println("Baking Chicken Pizza");
    }
}

TemplatePatternDemo.java
TemplatePatternDemo class will create an instance of VegPizza and ChickenPizza and call preparePizza method of each pizza type. For the output, we can verify that the sequence fo steps to prepare a pizza remains same for both pizza type but implementation of each step is different for each pizza type.
public class TemplatePatternDemo {
    public static void main(String[] args) {
        Pizza pizza = new VegPizza();
        pizza.preparePizza();
        System.out.println();
        pizza = new ChickenPizza();
        pizza.preparePizza();
    }
}

Output

Prepairing pizza base for Veg Pizza
Adding toppings for Veg Pizza
Baking Veg Pizza

Prepairing pizza base for Chicken Pizza
Adding toppings for Chicken Pizza
Baking Chicken Pizza

Guidelines for Implementing the Template Design Approach

To establish a resilient and maintainable implementation of the Template Approach, adhere to these recommended practices:
  • Identify the shared steps of the algorithm that persist consistently across diverse implementations. These steps will be incorporated into the Template method within the abstract class.

  • Consider offering default implementations for specific steps using hook methods. Hook methods act as optional steps that concrete subclasses can either override or employ the default implementation.

  • Recognize the steps that exhibit variation among different implementations. Designate these steps as abstract methods within the abstract class. Concrete subclasses will furnish specific implementations for these methods.

  • Exercise caution when utilizing hook methods, employing them sparingly and exclusively when deemed necessary. They should be reserved for steps that are optional or customizable, allowing subclasses the choice to either override or utilize the default behavior.

  • Declare the Template method as final to prevent subclasses from modifying the overarching structure of the algorithm. This ensures that the common sequence of steps is uniformly adhered to by all subclasses.

  • Maintain focus on the abstract class's primary role of providing a straightforward and lucid Template method. Steer clear of embedding intricate logic within the Template method, as it may complicate the algorithm's comprehensibility and maintenance.

  • Ensure that each method in the abstract class adheres to the Single Responsibility Principle. Each method should have a distinct and specific responsibility within the algorithm's context.

  • Leverage the Template Approach to instill consistency in algorithm implementation across diverse subclasses. This uniformity enhances code readability and maintainability.

  • Clearly document the Template method and its individual steps. Furnish details regarding the purpose of each step and any assumptions or prerequisites essential for the algorithm to function correctly.

Related Topics
Proxy Design Pattern
Filter Design Pattern
Singleton Design Pattern
Factory Design Pattern
Iterator Design Pattern
List of Design Patterns