Design Patters: Template Method

A template method pattern is a pattern that has a template. In this pattern, a superclass has template methods which have some abstract methods. These methods describe how abstract methods are called which are implemented by its subclasses.

Let’s see an example by creating a program which displays characters or strings for five times.

Class that is used in this program

  • AbstractDisplay: A class acting as a template method named display that calls abstract methods; open, print and close
  • CharDisplay: A class which implements AbstractDisplay
  • StringDisplay: A class which implements AbstractDisplay

AbstractDisplay class has a template method which calls abstract methods. It implements how they are used but does not implements these abstract methods.

# abstract_display.py
from abc import ABC, abstractmethod

class AbstractDisplay(ABC):
    @abstractmethod
    def open(self):
        pass

    @abstractmethod
    def print(self):
        pass

    @abstractmethod
    def close(self):
        pass

    def display(self):
        self.open()
        for _ in range(5):
            self.print()
        self.close()

Let’s define CharDisplay class, a subclass of AbstractDisplay class, that implements abstract methods; open, print, and close. This class is given an a character as an input and formats and prints it out.

# char_display.py
from abstract_display import AbstractDisplay

class CharDisplay(AbstractDisplay):
    def __init__(self, ch):
        self._ch = ch   
    
    def open(self):
        print("<<", end="")
    
    def print(self):
        print(self._ch, end="")

    def close(self):
        print(">>")

Let’s create another subclass, StringDisplay class which formats a given string and prints it out.

# string_display
from abstract_display import AbstractDisplay
import sys

class StringDisplay(AbstractDisplay):
    def __init__(self, string):
        self._string = string
        # Get a byte length
        self._width = len(string.encode("utf-8"))

    def open(self):
        self.print_line()
    
    def print(self):
        print(f"|{self._string}|")

    def close(self):
        self.print_line()

    def print_line(self):
        print('+', end='')
        for _ in range(self._width):
            print('-', end='')
        print('+')

Let’s call this program in which display methods are called from CharDisplay and StringDisplay.

# main.py
from char_display import CharDisplay
from string_display import StringDisplay

def main():
    d1 = CharDisplay('H')
    d2 = StringDisplay('Hello, world.')
    d1.display()
    d2.display()

if __name__ == "__main__":
    main()

One benefit of template method: it standardizes the logics in the method. Since all algorithms are defined in a template method in a superclass, you only need to modify the method as opposed to the case when you don’t have a template method in which case you need to modify all subclass methods.

Leave a comment