Padrão Template Method em Python
Published: 2020-12-14 08:31:14

O Template method é um **padrão de projeto comportamental**, ele define um esqueleto de um algorítimo em uma superclasse e permite que as subclasses especifiquem comportamentos particulares do algorítimo sem que o esqueleto seja modificado.

Este padrão sugere que o algorítimo seja dividido em etapas, estas etapas devem ser métodos e estes métodos devem ser chamados sequencialmente dentro de um método padrão.

Dessa forma é possível visualizar que estas chamadas particulares podem ser métodos abstratos (serão implementados por cada subclasse), métodos opcionais (tem uma implementação padrão que pode ser sobrescrito se necessário) e métodos gancho (Hook method, métodos que delegam parte de sua execução para um terceiro método abstrato que deve ser implementado na subclasse).

####Exemplo de Template Method em Python
```python
class AbstractClass(ABC):


    def template_method(self) -> None:

        self.base_operation1()
        self.required_operations1()
        self.base_operation2()
        self.hook1()
        self.required_operations2()
        self.base_operation3()
        self.hook2()

    def base_operation1(self) -> None:
        print("AbstractClass says: I am doing the bulk of the work")

    def base_operation2(self) -> None:
        print("AbstractClass says: But I let subclasses override some operations")

    def base_operation3(self) -> None:
        print("AbstractClass says: But I am doing the bulk of the work anyway")

    @abstractmethod
    def required_operations1(self) -> None:
        pass

    @abstractmethod
    def required_operations2(self) -> None:
        pass

    def hook1(self) -> None:
        pass

    def hook2(self) -> None:
        pass
```
A *AbstractClass* define o esqueleto do algorítimo, contém um método padrão que executa chamadas para os métodos etapa em uma ordem específica. Os métodos etapa podem ser abstratos ou conter implementações específicas.


```python
lass ConcreteClass1(AbstractClass):
    def required_operations1(self) -> None:
        print("ConcreteClass1 says: Implemented Operation1")

    def required_operations2(self) -> None:
        print("ConcreteClass1 says: Implemented Operation2")


class ConcreteClass2(AbstractClass):

    def required_operations1(self) -> None:
        print("ConcreteClass2 says: Implemented Operation1")

    def required_operations2(self) -> None:
        print("ConcreteClass2 says: Implemented Operation2")

    def hook1(self) -> None:
        print("ConcreteClass2 says: Overridden Hook1")
```
As *ConcreteClasses* implementam todos os métodos abstratos requeridos, eles também podem reescrever os métodos etapa mas nunca o método padrão (*template_method()*).

De maneira geral o Template Method pode ser utilizado quando há necessidade de que o cliente entenda apenas parte do algorítimo e não toda sua estrutura. Também pode ser utilizado quando se tem várias classes com algorítimos similares, estes são colocados dentro da superclasse deixando as variações para as subclasses, eliminando duplicação de código.

A implementação em Python não tem nenhuma particularidade em relação a implementação em Java.

***
**Referências**
[Padrões de Projeto](https://diogomoreira.gitbook.io/padroes-de-projeto/) (Diogo Moreira, 2020)
[Mergulho nos Padrões de Projeto - v2020-1.14](https://refactoring.guru/pt-br/design-patterns/book) (Alexander Shvets, 2020)
*Os códigos usados como exemplo foram retirados do livro Mergulho nos Padrões de Projeto.*