Design Patterns – Template Method Pattern: Abstract Classes vs Interface Delegation

design-patternsobject-orientedtemplate-method

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?

Best Answer

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.