Template method pattern - Java - Explained
Intent
Define the skeleton of an algorithm in the superclass and defer (postpone) some steps to the subclass. The template method lets subclasses define certain steps of an algorithm without changing the algorithm structure.
This is the type of behavioral design pattern where inheritance is used to describe algorithm and flow of control. Superclass defines the default and abstract methods and lets subclass provide an implementation of abstract methods.
Applicability/problem it solves?
As the name says it is a template that can be extended by subclass and alter a few things as per business needs in the subclass.
Well, an interesting thing here is usually subclass doesn't call a parent it just provides an implementation of a few abstract methods which are being called by the parent class(superclass) in the algorithm which is already defined in the superclass.
The template provides the reusability and extensibility of existing steps in the algorithm.
below are some applicability of template pattern:
- To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary.
means to provide base steps of an algorithm in the base class and let subclass implement the methods that can vary.
when common behavior among subclasses should be factored and localized in a common class to avoid code duplication.
To control subclass extensions. You can define a template method that calls "hook" operation at specific points, thereby permitting extensions only at those points.
Design Problem
Consider you are working for eCommerce site implementation and you want to provide a solution for placeOrder feature where placeOrder can be from Web or InStore. When place order is done by customer there are 5 things happens sequentially as below : placeOrder() doBasicCartValidations(); createOrderInERP(); setDeliveryAddress(); takePayment();
deliveryaddress and the way payment is taken is different if its web-order, web-pickup-instore-order and In-store order, all other methods are shared.
solution design
Please refer to below solution design for the problem :
code
public class SimpleTemplateMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
System.out.println("#### Customer performing placeOrder from Regular Web Checkout#### ");
PlaceOrderTemplate webCheckoutPlaceOrder = applicationContext.getBean(WebCheckoutPlaceOrder.class);
webCheckoutPlaceOrder.placeOrder();
System.out.println("\n#### Customer performing placeOrder from Web Checkout by selecting PickUp in store ####");
PlaceOrderTemplate webCheckoutPickUpInStorePlaceOrder = applicationContext.getBean(WebCheckoutPickUpInStorePlaceOrder.class);
webCheckoutPickUpInStorePlaceOrder.placeOrder();
System.out.println("\n#### Customer performing placeOrder from Instore ####");
PlaceOrderTemplate inStorePlaceOrder = applicationContext.getBean(InStorePlaceOrder.class);
inStorePlaceOrder.placeOrder();
}
}
// abstract template class
@Component
public abstract class PlaceOrderTemplate {
public final void placeOrder() {
doBasicCartValidations();
setDeliveryAddress();
takePayment();
createOrderInERP();
}
public final void doBasicCartValidations() {
System.out.println("Doing basic cart validations");
}
public final void createOrderInERP() {
System.out.println("Creating order in ERP");
}
public abstract void setDeliveryAddress();
public abstract void takePayment();
}
// template implementation classes
@Component
public class WebCheckoutPickUpInStorePlaceOrder extends PlaceOrderTemplate{
@Override
public void setDeliveryAddress() {
System.out.println("WebCheckoutPickUpInStorePlaceOrder : setting store address selected by the customer during checkout as delivery address" );
}
@Override
public void takePayment() {
System.out.println("WebCheckoutPickUpInStorePlaceOrder : taking payment from cart from webstore" );
}
}
@Component
public class WebCheckoutPlaceOrder extends PlaceOrderTemplate {
@Override
public void setDeliveryAddress() {
System.out.println("WebCheckoutPlaceOrder : setting customer's address provided by the customer during checkout as delivery address");
}
@Override
public void takePayment() {
System.out.println("WebCheckoutPickUpInStorePlaceOrder : taking payment from cart from webstore");
}
}
@Component
public class InStorePlaceOrder extends PlaceOrderTemplate{
@Override
public void setDeliveryAddress() {
System.out.println("InStorePlaceOrder : setting store address as delivery address");
}
@Override
public void takePayment() {
System.out.println("InStorePlaceOrder : processing instore payment process");
}
}
please click here for complete github code .
Structure Template Method Pattern
The template pattern structure has abstract classes and concrete classes.
Abstract class: This defines the core algorithm steps and also provide abstract methods for subclasses to provide definition.
Concrete class: This extends the template class and expected to provide abstract method definition . This can override all methods (steps in the algo) but not the actual template method itself (usually template method is defined as final).
Hooks in Template method - a type of template method pattern.
In template method pattern a hook is a method that is declared in the abstract class, but only given an empty or default implementation.
This is simple yet powerful technique for code insertion in the parent algorithm ( either use what is provided or provide your implementation)
Many enterprise solutions/spring applications use this to provide the ability to subclasses to provide alternate method implementation or additoinal steps in the algorithm of template methods.
In our example above doBasicCartValidation() method can act like a hook where if InStorePlaceOrder has some different validations those can be hooked by just overriding the method.
As a rule, when subclass must provide an implementation of the method or step in the algorithm then use abstract subclasses and use hooks when part of the algorithm is optional. With hooks, a subclass may choose to implement that hook, but it doesn’t have to.
Pros and Cons
Pros
- can help code reuse , duplicate code can be moved to abstract class.
- Provide extensibility to the algorithm by providing ability to subclass and allow only specific methods to override .
Cons
- A contract must not be complex, means if there are many steps for subclass to provide implementation there could be unwanted complexity. For minimum no of steps its manageable .
- Liskov Substitution Principle is violated by suppressing a default step implementation via a subclass.
Relation with other patterns
- Template method and Strategy pattern
Template methods use inheritance to vary part of an algorithm. Strategies use delegation by object composition to vary the entire algorithm.
As the template method works with inheritance its class level, means it's static however strategy is based on object composition means it's dynamic (can change strategy at runtime).
Subscribe to my newsletter
Read articles from Aditya Chaudhari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Aditya Chaudhari
Aditya Chaudhari
building efficient, scalable and maintainable enterprise e-commerce applications | Technical Architect | SAP Commerce Cloud (hybris) | Java | Spring | Mirakl