6.5. Template Method

  • EN: Template Method

  • PL: Metoda szablonowa

  • Type: class

6.5.1. Pattern

  • Bank application with audit trail (all actions)

  • Record task history

  • Audits

../../_images/designpatterns-templatemethod-pattern-1.png
../../_images/designpatterns-templatemethod-pattern-2.png

6.5.2. Problem

  • Duplicated code

  • Not enforced to record in audit trail

design-patterns/behavioral/img/designpatterns-templatemethod-problem.png

from dataclasses import dataclass


class AuditTrail:
    def record(self) -> None:
        print('Audit')


@dataclass
class TransferMoneyTask:
    audit_trail: AuditTrail

    def execute(self):
        self.audit_trail.record()
        print('Transfer Money')


@dataclass
class GenerateReportTask:
    audit_trail: AuditTrail

    def execute(self):
        self.audit_trail.record()
        print('Generate Report')


if __name__ == '__main__':
    audit_trail = AuditTrail()
    task = TransferMoneyTask(audit_trail)
    task.execute()
    # Audit
    # Transfer Money

6.5.3. Solution

../../_images/designpatterns-templatemethod-solution.png
../../_images/designpatterns-templatemethod-vs-inheritance.png
../../_images/designpatterns-templatemethod-vs-strategy.png

from abc import ABC, abstractmethod
from dataclasses import dataclass


class AuditTrail:
    def record(self) -> None:
        print('Audit')


@dataclass
class Task(ABC):
    audit_trail: AuditTrail = AuditTrail()

    def execute(self) -> None:
        self.audit_trail.record()
        self.do_execute()
        print('Transfer Money')

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

class GenerateReportTask(Task):
    def do_execute(self) -> None:
        print('Generate Report')

class TransferMoneyTask(Task):
    def do_execute(self) -> None:
        print('Transfer Money')


if __name__ == '__main__':
    task = TransferMoneyTask()
    task.execute()
    # Audit
    # Transfer Money

6.5.4. Assignments