G2Labs Grzegorz Grzęda
Template Method design pattern
May 18, 2023
Suppose that you want to create an architecture for your simple computing software. For each case you have to input some integers and perform some calculations.
Use case: The user inputs some integers, and as a result, the software computes variations of calculus computations (all of the numbers are summed up to a single result value). Depending on the algorithm, each number may be prepared for calculations, as well as the end result.
This means, that for every algorithm there is the ‘summing’ part, common for every one of them. We know this - we can delegate this functionality to a super class. The second part is the computation structure. First we have to condition the input values. After the summing we have to condition the end result.
Those two conditioning processes are different for each algorithm. They will be implemented in the subclasses.
Example project
This project can be found on my GitHub page. It has the following structure:
The main.cpp
and Makefile
are self explanatory (I hope). If not, you can visit
my other Design Pattern posts and dive deeper.
The AComputer
is the abstract superclass, holding the algorithm, memory management and
all the mechanisms needed to perform the task.
|
|
Here you see the prepare()
and finalize()
template methods to be implemented
in the subclasses, holding specific details about the algorithms.
There are two: SumOfSquares
and RootsSummed
. The first one:
|
|
Simply squares the input data. The summing is done in the superclass.
The RootsSummed
:
|
|
Takes the square root of each input value, gets summed in the superclass and takes the square root of the result. Just a fancy algorithm.
Finally, the main.cpp
:
|
|
Here the program takes the input values (if supplied), initiates the two algorithms
and performs computations. Lastly, the results are printed. Notice, that sosq
and
rtsm
are both instances of AComputer
. We have access only to put(int)
,
compute()
and getResults()
. The specialized methods prepare()
and finalize()
are obscured. The AComputer
handles all the interactions and sequencing needed.
The example run:
You can see, that the Template Method is actually the essence of inheritance. But, here it is put to work in a specific way. The methods need to be called in the superclass in the same order each time - the algorithm method. The subclasses just provide the lacking functionality, the superclass didn’t have. This scaffold lets us create as many algorithms as needed. We could place the algorithms in a collection and perform computation sequentially.
Benefits
We get:
- Simple architecture based on inheritance,
- Grouping of the sequence and data handling in the super class,
- When using delegation instead of inheritance, we get the Strategy Design Pattern, where we can replace whole algorithms.
Traps
We have to watch out:
- we have to set the abstract methods as protected, so that no one outside of the algorithm would access the without order and care of the superclass,
- When returning object implementing interfaces from subclass method we actually use Factory Method instead of Template Method.
Conclusion
Don’t underestimate the power of the Template Method Design Pattern! Such a simple solution may save you from the hassle of dealing with many detached classes, with undisclosed similarities.