模板方法模式
本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 52 课,共 64 课。
模板方法模式在基类中定义算法的框架,让子类可以重写特定步骤,而不改变算法的结构。
下面是一个包含模板方法的基类:
class DataProcessor:
def process(self):
"""定义算法结构的模板方法"""
self.read_data()
self.process_data()
self.save_data()
def read_data(self):
print("Reading data...")
def process_data(self):
raise NotImplementedError("Subclasses must implement this")
def save_data(self):
print("Saving data...")模板方法 process() 定义了算法步骤,而 process_data() 留给子类实现。
创建实现抽象方法的具体类:
class CSVProcessor(DataProcessor):
def process_data(self):
print("Processing CSV data")
class JSONProcessor(DataProcessor):
def process_data(self):
print("Processing JSON data")每个具体类都会提供所需步骤的具体实现。
使用模板方法:
csv_processor = CSVProcessor()
csv_processor.process()
print() # 空行
json_processor = JSONProcessor()
json_processor.process()再用游戏模板创建一个示例:
class Game:
def play(self):
"""用于玩游戏的模板方法"""
self.start_game()
self.play_game()
self.end_game()
def start_game(self):
print("Game started!")
def play_game(self):
raise NotImplementedError("Define the game rules")
def end_game(self):
print("Game ended!")
class Chess(Game):
def play_game(self):
print("Playing chess - thinking strategically...")
class Soccer(Game):
def play_game(self):
print("Playing soccer - running and kicking...")
chess = Chess()
chess.play()输出:
Reading data...
Processing CSV data
Saving data...
Reading data...
Processing JSON data
Saving data...
Game started!
Playing chess - thinking strategically...
Game ended!要点:模板方法模式在父类中定义通用的算法结构,同时允许子类自定义具体步骤。父类控制整体流程,而子类提供具体实现。这样既能确保结构一致,又能让各个步骤保持灵活。
挑战
中等在 template.py 中实现模板方法模式。抽象 Report 类拥有模板方法 generate(),它总是按相同顺序运行相同的三个步骤:header()、body()、footer()。
header()由每个报告共享,并输出=== Report ===。body()是抽象方法:每个子类输出自己的内容。footer()是一个带默认实现的钩子,=== End ===,子类可以重写它。
然后编写两个具体的报告类:
SalesReport(total)将总额存储在self._total中,并在主体中输出Total sales: {total}。InventoryReport(items)将列表存储在self._items中,在主体中为每个项目输出Item: {item},并重写页脚以输出=== {count} items ===。
driver.py 已锁定:它会创建报告并调用它们的 generate()。子类之间只有步骤不同;步骤的顺序只在基类中定义一次。
亲手试试
from template import SalesReport, InventoryReport
# 测试用例处理代码(不要修改)
test_case = input()
if test_case == "sales_test":
SalesReport(1500).generate()
elif test_case == "inventory_test":
InventoryReport(["Laptop", "Mouse"]).generate()
elif test_case == "both_test":
for report in [SalesReport(200), InventoryReport(["Pen"])]:
report.generate()
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Python 在线编译器