Шаблонний метод на Python
Шаблонний метод — це поведінковий патерн, який визначає кістяк алгоритму в суперкласі та змушує підкласи реалізувати конкретні кроки цього алгоритму.
Складність:
Популярність:
Застосування: Шаблонні методи можна зустріти в багатьох бібліотечних класах Python. Розробники створюють їх, щоб дозволити клієнтам легко та швидко розширювати стандартний код за допомогою спадкування.
Ознаки застосування патерна: Клас змушує своїх нащадків реалізувати методи-кроки, але самостійно реалізовує структуру алгоритму.
Концептуальний приклад
Цей приклад показує структуру патерна Шаблонний метод , а саме — з яких класів він складається, які ролі ці класи виконують і як вони взаємодіють один з одним.
main.py: Приклад структури патерна
from abc import ABC, abstractmethod
class AbstractClass(ABC):
"""
The Abstract Class defines a template method that contains a skeleton of
some algorithm, composed of calls to (usually) abstract primitive
operations.
Concrete subclasses should implement these operations, but leave the
template method itself intact.
"""
def template_method(self) -> None:
"""
The template method defines the skeleton of an algorithm.
"""
self.base_operation1()
self.required_operations1()
self.base_operation2()
self.hook1()
self.required_operations2()
self.base_operation3()
self.hook2()
# These operations already have implementations.
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")
# These operations have to be implemented in subclasses.
@abstractmethod
def required_operations1(self) -> None:
pass
@abstractmethod
def required_operations2(self) -> None:
pass
# These are "hooks." Subclasses may override them, but it's not mandatory
# since the hooks already have default (but empty) implementation. Hooks
# provide additional extension points in some crucial places of the
# algorithm.
def hook1(self) -> None:
pass
def hook2(self) -> None:
pass
class ConcreteClass1(AbstractClass):
"""
Concrete classes have to implement all abstract operations of the base
class. They can also override some operations with a default implementation.
"""
def required_operations1(self) -> None:
print("ConcreteClass1 says: Implemented Operation1")
def required_operations2(self) -> None:
print("ConcreteClass1 says: Implemented Operation2")
class ConcreteClass2(AbstractClass):
"""
Usually, concrete classes override only a fraction of base class'
operations.
"""
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")
def client_code(abstract_class: AbstractClass) -> None:
"""
The client code calls the template method to execute the algorithm. Client
code does not have to know the concrete class of an object it works with, as
long as it works with objects through the interface of their base class.
"""
# ...
abstract_class.template_method()
# ...
if __name__ == "__main__":
print("Same client code can work with different subclasses:")
client_code(ConcreteClass1())
print("")
print("Same client code can work with different subclasses:")
client_code(ConcreteClass2())
Output.txt: Результат виконання
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass1 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass1 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Same client code can work with different subclasses:
AbstractClass says: I am doing the bulk of the work
ConcreteClass2 says: Implemented Operation1
AbstractClass says: But I let subclasses override some operations
ConcreteClass2 says: Overridden Hook1
ConcreteClass2 says: Implemented Operation2
AbstractClass says: But I am doing the bulk of the work anyway
Шаблонний метод іншими мовами програмування