mirror of
https://github.com/rjNemo/design-patterns
synced 2026-06-12 05:26:40 +00:00
add code example
This commit is contained in:
parent
eb37c2ddc3
commit
16bd6a2d1a
3 changed files with 107 additions and 0 deletions
57
behavioral/template/abstract_class.py
Normal file
57
behavioral/template/abstract_class.py
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
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):
|
||||||
|
print("AbstractClass says: I am doing the bulk of the work")
|
||||||
|
|
||||||
|
def base_operation2(self):
|
||||||
|
print("AbstractClass says: But I let subclasses override some operations")
|
||||||
|
|
||||||
|
def base_operation3(self):
|
||||||
|
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):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def required_operations2(self):
|
||||||
|
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):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def hook2(self):
|
||||||
|
pass
|
||||||
29
behavioral/template/concrete_classes.py
Normal file
29
behavioral/template/concrete_classes.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
from behavioral.template.abstract_class import AbstractClass
|
||||||
|
|
||||||
|
|
||||||
|
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):
|
||||||
|
print("ConcreteClass1 says: Implemented Operation1")
|
||||||
|
|
||||||
|
def required_operations2(self):
|
||||||
|
print("ConcreteClass1 says: Implemented Operation2")
|
||||||
|
|
||||||
|
|
||||||
|
class ConcreteClass2(AbstractClass):
|
||||||
|
"""
|
||||||
|
Usually, concrete classes override only a fraction of base class' operations.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def required_operations1(self):
|
||||||
|
print("ConcreteClass2 says: Implemented Operation1")
|
||||||
|
|
||||||
|
def required_operations2(self):
|
||||||
|
print("ConcreteClass2 says: Implemented Operation2")
|
||||||
|
|
||||||
|
def hook1(self):
|
||||||
|
print("ConcreteCLass2 says: Overridden Hook1")
|
||||||
21
behavioral/template/main.py
Normal file
21
behavioral/template/main.py
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
from behavioral.template.abstract_class import AbstractClass
|
||||||
|
from behavioral.template.concrete_classes import ConcreteClass1, ConcreteClass2
|
||||||
|
|
||||||
|
|
||||||
|
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())
|
||||||
Loading…
Reference in a new issue