Паттерн "Шаблонный метод" с наследованием в Python реализуется путем создания абстрактного базового класса, который определяет скелет алгоритма. Этот класс содержит методы, некоторые из которых являются абстрактными и должны быть реализованы в подклассах. Конкретные подклассы переопределяют эти абстрактные методы, предоставляя конкретную реализацию шагов алгоритма, сохраняя общую структуру, определенную в базовом классе.
class AbstractClass:
def template_method(self):
self.hook1()
self.required_operation1()
self.hook2()
self.required_operation2()
def required_operation1(self):
raise NotImplementedError
def required_operation2(self):
raise NotImplementedError
def hook1(self):
pass # Optional hook
def hook2(self):
pass # Optional hook
class ConcreteClassA(AbstractClass):
def required_operation1(self):
print("ConcreteClassA: Implemented Operation1")
def required_operation2(self):
print("ConcreteClassA: Implemented Operation2")
class ConcreteClassB(AbstractClass):
def required_operation1(self):
print("ConcreteClassB: Implemented Operation1")
def required_operation2(self):
print("ConcreteClassB: Implemented Operation2")
def hook1(self):
print("ConcreteClassB: Overridden Hook1")
# Usage
a = ConcreteClassA()
a.template_method()
b = ConcreteClassB()
b.template_method()
В примере выше, AbstractClass
определяет template_method
, который определяет порядок выполнения шагов. required_operation1
и required_operation2
являются абстрактными и должны быть реализованы в подклассах. hook1
и hook2
являются "хуками", которые могут быть переопределены подклассами для добавления дополнительного поведения.
Паттерн "Шаблонный метод" (Template Method) - это поведенческий паттерн проектирования, который определяет скелет алгоритма в базовом классе, но позволяет подклассам переопределять некоторые шаги алгоритма, не изменяя его структуру в целом. Он использует наследование для достижения этой цели.
Вот пример реализации на Python:
class AbstractClass:
"""
Определяет скелет алгоритма.
"""
def template_method(self):
"""
Определяет порядок вызова примитивных операций для
реализации алгоритма. Может вызывать как конкретные, так и
абстрактные операции.
"""
self.hook_before() # Hook - опциональный шаг
self.primitive_operation1()
self.primitive_operation2()
self.hook_after() # Hook - опциональный шаг
def primitive_operation1(self):
"""
Требует, чтобы подклассы реализовали эти операции.
"""
raise NotImplementedError("Подклассы должны реализовать primitive_operation1")
def primitive_operation2(self):
"""
Требует, чтобы подклассы реализовали эти операции.
"""
raise NotImplementedError("Подклассы должны реализовать primitive_operation2")
def hook_before(self):
"""
Hook, предоставляющий подклассам возможность переопределить его.
Он делает это по желанию.
"""
pass
def hook_after(self):
"""
Hook, предоставляющий подклассам возможность переопределить его.
Он делает это по желанию.
"""
pass
class ConcreteClass1(AbstractClass):
"""
Реализует примитивные операции для выполнения конкретных шагов алгоритма.
"""
def primitive_operation1(self):
print("ConcreteClass1: Реализация operation1")
def primitive_operation2(self):
print("ConcreteClass1: Реализация operation2")
def hook_before(self):
print("ConcreteClass1: Hook before")
class ConcreteClass2(AbstractClass):
"""
Реализует примитивные операции другим способом.
"""
def primitive_operation1(self):
print("ConcreteClass2: Реализация operation1")
def primitive_operation2(self):
print("ConcreteClass2: Реализация operation2")
def hook_after(self):
print("ConcreteClass2: Hook after")
# Пример использования
concrete_class1 = ConcreteClass1()
print("ConcreteClass1:")
concrete_class1.template_method()
print("\nConcreteClass2:")
concrete_class2 = ConcreteClass2()
concrete_class2.template_method()
Объяснение:
template_method()
. Этот метод задает общую структуру алгоритма. Он вызывает абстрактные методы (primitive_operation1()
, primitive_operation2()
), которые должны быть реализованы в подклассах, а также может вызывать hook-методы (hook_before()
, hook_after()
), которые являются необязательными для переопределения.AbstractClass
и предоставляют конкретные реализации абстрактных методов (primitive_operation1()
и primitive_operation2()
). Они также могут переопределять hook-методы, чтобы изменить поведение алгоритма.