75 lines
No EOL
3.3 KiB
Markdown
75 lines
No EOL
3.3 KiB
Markdown
---
|
|
obj: concept
|
|
---
|
|
# Template Method Pattern
|
|
|
|
## **Description:**
|
|
The Template Method Pattern is a behavioral design pattern that defines the skeleton of an algorithm in the base class but allows subclasses to override specific steps of the algorithm without changing its structure. It provides a way to define the overall algorithm's structure while allowing customization of certain steps by subclasses. This pattern promotes code reuse and follows the "Don't Call Us, We'll Call You" principle, where the base class controls the flow of the algorithm.
|
|
|
|
**How it's Used:**
|
|
1. **Abstract Template Class**: Create an abstract base class (or interface) that defines the template method, which is the skeleton of the algorithm. The template method consists of a series of steps, some of which may be abstract or have default implementations.
|
|
2. **Concrete Subclasses**: Create concrete subclasses that inherit from the abstract template class. These subclasses provide concrete implementations for the abstract steps of the template method.
|
|
3. **Template Method**: The template method in the abstract base class controls the overall algorithm's flow by calling the individual steps. It should be marked as final or not overridable to prevent subclasses from altering the algorithm's structure.
|
|
|
|
## **Example:**
|
|
Let's create an example of the Template Method Pattern in [Python](../../languages/Python.md) for a beverage preparation process with a template method for brewing beverages.
|
|
```python
|
|
from abc import ABC, abstractmethod
|
|
|
|
# Step 1: Abstract Template Class
|
|
class Beverage(ABC):
|
|
def prepare(self):
|
|
self.boil_water()
|
|
self.brew()
|
|
self.pour_in_cup()
|
|
self.add_condiments()
|
|
|
|
@abstractmethod
|
|
def brew(self):
|
|
pass
|
|
|
|
@abstractmethod
|
|
def add_condiments(self):
|
|
pass
|
|
|
|
def boil_water(self):
|
|
print("Boiling water")
|
|
|
|
def pour_in_cup(self):
|
|
print("Pouring into cup")
|
|
|
|
# Step 2: Concrete Subclasses
|
|
class Tea(Beverage):
|
|
def brew(self):
|
|
print("Steeping the tea")
|
|
|
|
def add_condiments(self):
|
|
print("Adding lemon")
|
|
|
|
class Coffee(Beverage):
|
|
def brew(self):
|
|
print("Dripping coffee through filter")
|
|
|
|
def add_condiments(self):
|
|
print("Adding sugar and milk")
|
|
|
|
# Step 3: Client Code
|
|
def main():
|
|
tea = Tea()
|
|
coffee = Coffee()
|
|
|
|
print("Making tea:")
|
|
tea.prepare()
|
|
|
|
print("\nMaking coffee:")
|
|
coffee.prepare()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
In this [Python](../../languages/Python.md) example, we define a `Beverage` abstract base class (Step 1) with a `prepare` method that represents the template method. The `prepare` method calls four steps: `boil_water`, `brew`, `pour_in_cup`, and `add_condiments`. The `brew` and `add_condiments` methods are declared as abstract, allowing concrete subclasses (e.g., `Tea` and `Coffee`) to provide their implementations for these steps.
|
|
|
|
Concrete subclasses (Step 2) such as `Tea` and `Coffee` inherit from the `Beverage` class and provide their implementations for the `brew` and `add_condiments` steps.
|
|
|
|
In the `main` function (Step 3), we create instances of `Tea` and `Coffee` and invoke the `prepare` method on each, which follows the template method's algorithm for preparing beverages. Subclasses customize the steps to produce specific types of beverages while reusing the common template method structure. |