The Template Method design pattern defines the skeleton of an algorithm in a base class, allowing subclasses to provide specific implementations for certain steps of the algorithm. The pattern follows the "Hollywood Principle": "Don't call us, we'll call you." In other words, the base class (the template) controls the overall algorithm flow and delegates specific steps to the subclasses.
// Abstract Class
abstract class Vehicle {
public void start() {
// Step 1: Perform pre-start operations
performPreStartChecks();
// Step 2: Start the vehicle
startEngine();
// Step 3: Perform post-start operations
performPostStartTasks();
}
protected abstract void performPreStartChecks();
protected abstract void startEngine();
protected abstract void performPostStartTasks();
}
// Concrete Class
class Car extends Vehicle {
protected void performPreStartChecks() {
System.out.println("Performing pre-start checks for Car");
// Specific pre-start checks for Car
}
protected void startEngine() {
System.out.println("Starting the engine of Car");
// Start the engine of Car
}
protected void performPostStartTasks() {
System.out.println("Performing post-start tasks for Car");
// Specific post-start tasks for Car
}
}
// Concrete Class
class Truck extends Vehicle {
protected void performPreStartChecks() {
System.out.println("Performing pre-start checks for Truck");
// Specific pre-start checks for Truck
}
protected void startEngine() {
System.out.println("Starting the engine of Truck");
// Start the engine of Truck
}
protected void performPostStartTasks() {
System.out.println("Performing post-start tasks for Truck");
// Specific post-start tasks for Truck
}
}
public class Main {
public static void main(String[] args) {
Vehicle car = new Car();
car.start(); // Output: Performing pre-start checks for Car, Starting the engine of Car, Performing post-start tasks for Car
Vehicle truck = new Truck();
truck.start(); // Output: Performing pre-start checks for Truck, Starting the engine of Truck, Performing post-start tasks for Truck
}
}
In this example, we have an abstract Vehicle
class that serves as the template for starting a vehicle. It defines the overall algorithm for starting a vehicle but leaves certain steps to be implemented by the subclasses (Car
and Truck
).
The template method start()
in the Vehicle
class represents the overall algorithm for starting a vehicle. It consists of three steps that would be executed sequentially:
performPreStartChecks()
: This is a hook method declared as abstract in theVehicle
class. Subclasses must provide their specific implementation of pre-start checks.startEngine()
: This is also a hook method declared as abstract in theVehicle
class. Subclasses must implement this method to start the engine based on their specific implementation.performPostStartTasks()
: Another hook method declared as abstract in theVehicle
class. Subclasses must provide their specific implementation of post-start tasks.
The subclasses (Car
and Truck
) inherit the start()
method from the Vehicle
class and override the abstract methods to provide their own implementations.
In the Main
class, we create instances of Car
and Truck
and invoke the start()
method. The template method controls the flow of the algorithm, calling the appropriate hook methods based on the type of vehicle. The output demonstrates the specific steps executed for each type of vehicle.
The Templete Method pattern enables us to define the overall structure of the algorithm while delegating the implementation details to the subclasses.
Use the Template Method pattern when you want to let clients extend only particular steps of an algorithm, but not the whole algorithm or its structure.
- The Template Method lets you turn a monolithic algorithm into a series of individual steps which can be easily extended by subclasses while keeping intact the structure defined in a superclass.
Use the pattern when you have several classes that contain almost identical algorithms with some minor differences. As a result, you might need to modify both classes when the algorithm changes.
- When you turn such an algorithm into a template method, you can also pull up the steps with similar implementations into a superclass, eliminating code duplication. Code that varies between subclasses can remain in subclasses.
- For example, Almost all
Vehicle
(Car
,Truck
) might have similaropenDoor()
method implementations. We can pull up this implementation into the super class, eliminating code duplication.
- For example, Almost all