Template Method Pattern
Template Method pattern is a behavioural design pattern.
This pattern defines the steps of an algorithm and allows sub-classes to provide the implementation for one or more steps
It provides default implementation for one or more steps which are common for all or some of the subclasses
Template pattern defines the skeleton of an algorithm in a method,deferring some steps to subclasses.
Template pattern lets subclasses to redefine certain steps of an algorithm without changing the algorithm’s structure.
The main goal in this pattern is to create a template which can be used by subclasses.
Template is a method which defines steps of an algorithm.
Let’s understand Template Method pattern with below example
We know that placing an order in ecommerce website will have several steps
1) Add items to cart
2) Add delivery address
3) Provide payment details
4) Review order details
5) Confirm place order
We also know that, there could be different types of order
1) Regular order – Items delivered to customer
2) Store Pickup order – Customer picks up items from Store
Now most of the steps for both Order types are same and hence we can define a template for that and override specific methods in subclass
Let’s implement Template Method pattern
We can define one template method with the set of steps to be performed and make that method as final, So that every subclass can just follow it rather than overriding it.
Define common methods in the abstract class where we define template methods
Let subclass override specific methods
Step 1
Create an abstract class with template method
- package com.kb.template;
- public abstract class PlaceOrderTemplate {
- public final void placeOrder(){
- addToCart();
- setDeliveryAddress();
- setPaymentDetails();
- reviewOrderDetails();
- confirmOrder();
- }
- public abstract void setDeliveryAddress();
- public abstract void setPaymentDetails();
- public final void addToCart() {
- System.out.println("Items added to cart");
- }
- public final void reviewOrderDetails() {
- System.out.println("Review the order details");
- }
- public final void confirmOrder() {
- System.out.println("Place the order after reviewing");
- }
- }
package com.kb.template; public abstract class PlaceOrderTemplate { public final void placeOrder(){ addToCart(); setDeliveryAddress(); setPaymentDetails(); reviewOrderDetails(); confirmOrder(); } public abstract void setDeliveryAddress(); public abstract void setPaymentDetails(); public final void addToCart() { System.out.println("Items added to cart"); } public final void reviewOrderDetails() { System.out.println("Review the order details"); } public final void confirmOrder() { System.out.println("Place the order after reviewing"); } }
Step 2
Create a subclass for placing regular order and override specific methods
- package com.kb.template;
- public class RegularOrder extends PlaceOrderTemplate{
- @Override
- public void setDeliveryAddress() {
- System.out.println("Select or add new delivery address of customer");
- }
- @Override
- public void setPaymentDetails() {
- System.out.println("Provide payment details like Net banking, credit card");
- }
- }
package com.kb.template; public class RegularOrder extends PlaceOrderTemplate{ @Override public void setDeliveryAddress() { System.out.println("Select or add new delivery address of customer"); } @Override public void setPaymentDetails() { System.out.println("Provide payment details like Net banking, credit card"); } }
Step 3
Create a subclass for placing store pickup order and override specific methods
- package com.kb.template;
- public class StorePickupOrder extends PlaceOrderTemplate{
- @Override
- public void setDeliveryAddress() {
- System.out.println("Select nearest store for pickup");
- }
- @Override
- public void setPaymentDetails() {
- System.out.println("Pay at counter through cash/POS");
- }
- }
package com.kb.template; public class StorePickupOrder extends PlaceOrderTemplate{ @Override public void setDeliveryAddress() { System.out.println("Select nearest store for pickup"); } @Override public void setPaymentDetails() { System.out.println("Pay at counter through cash/POS"); } }
Step 4
Create a client class to test this pattern
- package com.kb.template;
- public class TemplatePatternClient {
- public static void main(String[] args) {
- System.out.println(" .........placing Regular order.........");
- PlaceOrderTemplate regularOrder = new RegularOrder();
- regularOrder.placeOrder();
- System.out.println(" .........placing Store pickup order.........");
- PlaceOrderTemplate storePickupOrder = new StorePickupOrder();
- storePickupOrder.placeOrder();
- }
- }
package com.kb.template; public class TemplatePatternClient { public static void main(String[] args) { System.out.println(" .........placing Regular order........."); PlaceOrderTemplate regularOrder = new RegularOrder(); regularOrder.placeOrder(); System.out.println(" .........placing Store pickup order........."); PlaceOrderTemplate storePickupOrder = new StorePickupOrder(); storePickupOrder.placeOrder(); } }
We can see that, for both types of order same steps have been followed using template method in the abstract class and overridden specific methods in subclass
Key points about Template method pattern
Define one template method in the abstract class and make it as final
This method should contain the list of steps to be followed by each subclass
Provide abstract methods for those methods which can have different implementations in subclass
Define the methods which can be common for all the sub-classes
Avoid duplication in the code, the general algorithm is implemented once in the abstract class along with method definition for generic functionality and specific methods are implemented in the subclasses.
This patterns let the subclasses implement specific behaviour (through method overriding)