Template method pattern is commonly implemented with abstract classes.
interface Algorithm
{
void perform();
}
abstract class AlgorithmBase implements Algorithm
{
abstract void step1();
abstract void step2();
private void finalStep()
{
// common implementation
}
// Template method
public final void perform()
{
step1();
step2();
finalStep();
}
}
public class AlgorithmA extends AlgorithmBase
{
void step1()
{
// step 1 implementation
}
void step2()
{
// step 2 implementation
}
}
using
Algorithm a = new AlgorithmA();
a.perform();
But some languages (like Swift) don't support abstract classes. Implementation of template method pattern is done through interface delegation.
protocol Algorithm
{
func perform()
}
protocol AlgorithmSteps
{
func step1()
func step2()
}
class AlgorithmBase: Algorithm
{
var delegate: AlgorithmSteps
init(delegate: AlgorithmSteps)
{
self.delegate = delegate
}
private func finalStep()
{
// common implementation
}
// Template method
final func perform()
{
delegate.step1()
delegate.step2()
finalStep()
}
}
class AlgorithmA : AlgorithmSteps
{
func step1()
{
// step 1 implementation
}
func step2()
{
// step 2 implementation
}
}
let a : Algorithm = AlgorithmBase(delegate: AlgorithmA())
a.perform()
Obviously if language does not support abstract classes the only way to go is using interface delegation, but what if it does? Then template method pattern can be implemented either way.
Does second implementation has any advantages in terms of good OOP practices vs first one?
1 Answer 1
Neither one is better than the other. It depends entirely on your point of view. In the first case, you should think of it as extending the logic of AlgorithmBase
. Suppose you have a class called DatabaseEntity
with class PersonEntity
deriving from it. Both of which save to the database, on the latter may want to override the validation logic prior to saving to ensure that firstName
and lastName
values are filled. DatabaseEntity
is still in charge of when these methods get called, but PersonEntity
redefines what it means to validate that instance.
In the second case, it is more about passing responsibility to another class. You probably wouldn't want to pass responsibility to another class in the case above. A PersonEntity
instance is perfectly suited to perform validation of itself. Rather take the example of a VehicleFactory
. Any class deriving from VehicleFactory
would have to return a Vehicle
instance, but suppose you want to generate also a person that drives the vehicle. It would be wrong to expect a derived class of VehicleFactory
to worry about that. Instead, it should have a PersonFactory
instance and delegate the job of creating a Person
instance to PersonFactory
. It is still a step in the process of creating a Vehicle
, but in contrast to the first example, some of the steps shouldn't be performed by that class or its derived classes.
TL;DR - It depends on what you need to have done, and whether or not steps 1 and 2 should be performed by a derived class.
Explore related questions
See similar questions with these tags.