Python设计模式详解之13 —— 模板方法模式
Template Method 设计模式 是一种行为型设计模式,用于定义一个操作的骨架,将某些步骤延迟到子类中实现,从而允许子类在不改变整体算法结构的情况下重新定义某些步骤。
在 Python 中,Template Method 模式通常使用基类的方法来定义通用算法框架,并通过子类覆盖特定步骤实现具体逻辑。
结构
- 抽象类: 提供算法的骨架,包含模板方法(定义算法步骤的顺序)和一些需要子类实现的抽象方法。
- 具体类: 实现抽象方法,定义算法的具体步骤。
代码示例
from abc import ABC, abstractmethod
class AbstractWorkflow(ABC):
"""抽象类,定义算法的骨架"""
def template_method(self):
"""模板方法,定义算法的框架"""
self.step_one()
self.step_two()
self.hook() # 可选步骤
self.step_three()
def step_one(self):
"""通用步骤"""
print("Step 1: Common implementation.")
@abstractmethod
def step_two(self):
"""需要子类实现的抽象方法"""
pass
@abstractmethod
def step_three(self):
"""需要子类实现的抽象方法"""
pass
def hook(self):
"""钩子方法,子类可选择性覆盖"""
print("Default hook: Optional step.")
class ConcreteWorkflowA(AbstractWorkflow):
"""具体实现 A"""
def step_two(self):
print("Step 2 (A): Specific implementation for A.")
def step_three(self):
print("Step 3 (A): Specific implementation for A.")
class ConcreteWorkflowB(AbstractWorkflow):
"""具体实现 B"""
def step_two(self):
print("Step 2 (B): Specific implementation for B.")
def step_three(self):
print("Step 3 (B): Specific implementation for B.")
def hook(self):
print("Custom hook: Overridden by B.")
# 客户端代码
def client_code(workflow: AbstractWorkflow):
workflow.template_method()
if __name__ == "__main__":
print("Running ConcreteWorkflowA:")
client_code(ConcreteWorkflowA())
print("\nRunning ConcreteWorkflowB:")
client_code(ConcreteWorkflowB())
运行结果
Running ConcreteWorkflowA:
Step 1: Common implementation.
Step 2 (A): Specific implementation for A.
Default hook: Optional step.
Step 3 (A): Specific implementation for A.
Running ConcreteWorkflowB:
Step 1: Common implementation.
Step 2 (B): Specific implementation for B.
Custom hook: Overridden by B.
Step 3 (B): Specific implementation for B.
模式要点
- 模板方法: 定义算法骨架,控制步骤的调用顺序。
- 抽象方法: 强制子类实现特定步骤。
- 钩子方法: 提供可选的扩展点,允许子类覆盖。
- 封装不变部分: 将通用逻辑放在基类中,确保不被子类破坏。
- 开放/封闭原则: 算法结构对扩展开放,对修改封闭。
优点
- 避免重复代码,将通用逻辑提取到基类。
- 子类只需关注特定步骤的实现,简化开发。
- 灵活扩展特定步骤,而无需修改算法框架。
缺点
- 如果算法步骤较多,可能导致类数量增加。
- 继承限制了灵活性,无法动态改变算法步骤。
适用场景
- 多个子类需要共享算法的通用部分。
- 需要通过子类定制算法的某些步骤。