Used to manage and execute different functions for different objects, where functions share some common code
The Template Pattern is implemented to perform different behaviors represented from context object using the template object(s).
It is what is being currently used in a lot of places, substituting the State Pattern to follow the modern practice of decentralization of state into smaller components for a more robust component architecture in most frameworks like React JS, Next JS etc.
In fact, React JS Hooks, which got introduced in 2016 and took the component driven framework world by a storm, implement the Template Model and Strategy Pattern logic under the hood !
Feel free to browse through this detailed blog on Strategy Pattern for reference :
Template Model Pattern is like a version of strategy pattern where the implementation is done through a parent abtract class instead of an interface to give the 2 options to the child classes -
- Polymorph the required methods
- Inherit the required methods right from how the parent defines them
Ok, but what is Polymorphing ?
Polymorphism is one of the fundamentals of Object Oriented Programming. What it lays down is this -
"Child classes extending an abstract parent class have to implement the methods (functions) prescribed by the parent class.
This is other done by inheriting i.e. copying the method implementation from the parent, or by coming up with their own implementation of the same method (aka polymorphing), which shall override the parent's implementaion."
Yeah sure, but what exactly is an abstract parent class ?
In polymorphism, we use the concept of an abstract parent class where the parent class just provides a base template with some variables and functions defined
Child classes extending this template can either inherit this template's definitions or come up with their own custom implementations of the methods, variables declared in the template (aka polymorphing the methods, variables).
Salient features :
- Abstract parent classes can't be instantiated (can't make objects directly from these classes)
- Any abstract class that contains abstract methods, concrete methods (methods that can't be polymorphed) or both
- Any class which extends this abstract class must override the abstract methods.
- Abstract methods can be declared only in abstract classes.
So how is this any different from the Strategy Pattern ?
So how is this any different from the State Pattern ?
|STRATEGY PATTERN||TEMPLATE MODEL PATTERN|
|The base layer is an interface||The base layer is a parent abstract class|
|Child classes compulsorily have to implement all the logic declared in the base layer themselves||Child classes have the flexibility to either implement all the logic declared in the base layer themselves (polymorphing) or simple inherit it from the parent|
The source code for all prominent design patterns has been properly implemented and documented in this GitHub repostitory by me.
Here, in this article, we will be building a simple application that mimics digital transaction processing like any payments gateway like Google Pay, PayTM or any bank in the sense that we will layout the structure of how an audit trail is implemented by classes for transfering money and generating reports 🔥
Setting up the Context
This class simply generates our context object i.e. our audit trail for the task method to do some functions on
Implementing the Template
A template is just common interface for exposing a multitude of functionalities offered by our software
It is implemented as an abstract parent class or as an interface in all OOP languages. It just has to enlist the methods that all classes extending it can polymorph or inherit in their own way for providing the - "same interface - different/same function" feature.
We have defined 1 template - Task (which will be our Template class), with the following abstract and concrete methods defined.
|Method Name||Method Type||Function of Method|
||Prototype of method for implementing the logic of the audit task being executed (eg :generate a report, transfer money )|
||Fixed method for running some startup middleware processing irrespective of whichever audit task you wish to execute (eg: generate a report, transfer money)|
- Here, the protected keyword is used to ensure that only the child classes extending this class can access this method and no one else.
It gives a sort of role based access control to our doExecute( ) method.
- Also, as visible here, the execute( ) method is what is called on each task to do 2 things
- First, run some middleware that starts the transaction and records it
- Run the task i.e. the crux of this transaction
Implementing the Concrete classes
Child classes that extend their respective Template class and implement the abstracted prototype methods listed by the interface that they extend
|Concrete Class Name||Function|
||Implementation of the logic for transferring money will exist here|
||Implementation of the logic generating a report will exist here|
Using this pattern in our application
Import all the necessary classes and modules into main.java for a final showdown of our application ! Here, I'll be running both tasks just to show how some common code as well as some unique code, will run for both these tasks
var task = new TransferMoneyTask(); task.execute(); var task2 = new GenerateReportTask(); task.execute(); task2.execute();
Congrats on unlocked the secret of how most modern implementations of reactive applications work under the hood. You should feel pretty comfortable now developing the state responsive functionalities in a decentralized but structured manner in your applications. Until next time...
Whatever I have learnt and implemented here in code as well as the explanation is all from the teachings of the brilliant Mosh Hamedani and his course on Design Patterns which I would recommend you to take if you are really interested in exploring the beauty of Object Oriented Programming