HoRain云--Python 模板方法模式

发布时间:2026/6/8 10:29:59

HoRain云--Python 模板方法模式 HoRain 云小助手个人主页⛺️生活的理想就是为了理想的生活!⛳️ 推荐前些天发现了一个超棒的服务器购买网站性价比超高大内存超划算忍不住分享一下给大家。点击跳转到网站。目录⛳️ 推荐为什么需要模板方法模式代码复用扩展性控制反转模板方法模式的结构核心组件说明基本语法和实现抽象基类的定义实例具体子类的实现实例实际应用示例示例1数据处理的模板实例示例2饮料制作模板实例模板方法模式的变体1. 带参数的模板方法实例2. 多步骤模板方法实例最佳实践和注意事项1. 合理使用抽象方法2. 模板方法的访问控制3. 错误处理实例实践练习练习1实现文件导出模板练习2改进饮料制作模板总结主要优点适用场景核心要点模板方法模式是一种行为设计模式它定义了一个操作中的算法骨架而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变算法结构的情况下重新定义算法中的某些特定步骤。简单来说就像做菜的食谱一样食谱规定了做菜的步骤顺序洗菜、切菜、炒菜、装盘但具体怎么洗、怎么切、怎么炒可以由不同的厨师根据自己的风格来实现。为什么需要模板方法模式代码复用模板方法模式将不变的行为移到超类中避免了子类中的代码重复。多个子类可以共享同一个模板方法定义的算法结构。扩展性子类可以通过重写钩子方法或具体步骤方法来扩展或修改算法的部分行为而不需要改变算法的整体结构。控制反转父类控制着算法的执行流程子类只需要关注自己需要实现的特定步骤实现了好莱坞原则——不要打电话给我们我们会打电话给你。模板方法模式的结构让我们通过一个类图来理解模板方法模式的结构核心组件说明组件职责说明AbstractClass定义算法骨架包含模板方法和抽象步骤方法ConcreteClass实现具体步骤实现父类定义的抽象方法template_method模板方法定义算法的不变部分step1, step2抽象方法需要子类实现的具体步骤hook钩子方法可选步骤子类可选择是否重写基本语法和实现抽象基类的定义实例from abc import ABC, abstractmethodclass AbstractClass(ABC):模板方法模式的抽象基类def template_method(self):模板方法 - 定义算法骨架self.step1()self.step2()self.hook()self.step3()abstractmethoddef step1(self):抽象方法1 - 必须由子类实现passabstractmethoddef step2(self):抽象方法2 - 必须由子类实现passdef step3(self):具体方法 - 已有默认实现print(执行步骤3 - 默认实现)def hook(self):钩子方法 - 可选步骤子类可选择重写print(执行钩子方法 - 默认什么都不做)具体子类的实现实例class ConcreteClassA(AbstractClass):具体实现类Adef step1(self):print(ConcreteClassA - 执行步骤1)def step2(self):print(ConcreteClassA - 执行步骤2)def hook(self):print(ConcreteClassA - 重写钩子方法添加额外功能)class ConcreteClassB(AbstractClass):具体实现类Bdef step1(self):print(ConcreteClassB - 执行步骤1)def step2(self):print(ConcreteClassB - 执行步骤2)# 不重写hook方法使用默认实现实际应用示例让我们通过几个实际的例子来深入理解模板方法模式的应用。示例1数据处理的模板实例from abc import ABC, abstractmethodimport jsonimport csvclass DataProcessor(ABC):数据处理模板def process_data(self, input_file, output_file):数据处理模板方法print(f开始处理数据: {input_file} - {output_file})# 读取数据data self.read_data(input_file)print(f读取到 {len(data)} 条数据)# 转换数据transformed_data self.transform_data(data)print(数据转换完成)# 保存数据self.save_data(transformed_data, output_file)print(数据保存完成)# 清理工作self.cleanup()abstractmethoddef read_data(self, file_path):读取数据 - 抽象方法passabstractmethoddef transform_data(self, data):转换数据 - 抽象方法passdef save_data(self, data, file_path):保存数据 - 具体方法with open(file_path, w, encodingutf-8) as f:if isinstance(data, list):for item in data:f.write(str(item) \n)else:f.write(str(data))def cleanup(self):清理工作 - 钩子方法print(清理工作完成)class JSONProcessor(DataProcessor):JSON 数据处理器def read_data(self, file_path):with open(file_path, r, encodingutf-8) as f:return json.load(f)def transform_data(self, data):# 简单的转换将所有字符串值转为大写if isinstance(data, dict):return {k: v.upper() if isinstance(v, str) else vfor k, v in data.items()}elif isinstance(data, list):return [item.upper() if isinstance(item, str) else itemfor item in data]return dataclass CSVProcessor(DataProcessor):CSV 数据处理器def read_data(self, file_path):data []with open(file_path, r, encodingutf-8) as f:reader csv.DictReader(f)for row in reader:data.append(row)return datadef transform_data(self, data):# 为每条记录添加处理时间戳import datetimetimestamp datetime.datetime.now().isoformat()for record in data:record[processed_at] timestampreturn datadef cleanup(self):重写清理方法添加额外清理逻辑print(CSV 处理器清理完成)print(释放 CSV 解析器资源)# 使用示例if __name__ __main__:# 创建测试数据import os# 测试 JSON 处理器json_data {name: john, age: 30, city: new york}with open(test.json, w) as f:json.dump(json_data, f)json_processor JSONProcessor()json_processor.process_data(test.json, output_json.txt)print(\n *50 \n)# 测试 CSV 处理器csv_data name,age,city\njohn,30,new york\njane,25,los angeleswith open(test.csv, w) as f:f.write(csv_data)csv_processor CSVProcessor()csv_processor.process_data(test.csv, output_csv.txt)# 清理测试文件for file in [test.json, test.csv, output_json.txt, output_csv.txt]:if os.path.exists(file):os.remove(file)示例2饮料制作模板实例from abc import ABC, abstractmethodclass BeverageMaker(ABC):饮料制作模板def make_beverage(self):制作饮料的模板方法self.boil_water()self.brew()self.pour_in_cup()if self.customer_wants_condiments():self.add_condiments()self.serve()def boil_water(self):烧水 - 具体方法print(烧开水)abstractmethoddef brew(self):冲泡 - 抽象方法passdef pour_in_cup(self):倒入杯子 - 具体方法print(倒入杯子中)abstractmethoddef add_condiments(self):添加调料 - 抽象方法passdef customer_wants_condiments(self):钩子方法 - 客户是否要调料return Truedef serve(self):上饮料 - 具体方法print(饮料制作完成请享用)class CoffeeMaker(BeverageMaker):咖啡制作def brew(self):print(用沸水冲泡咖啡粉)def add_condiments(self):print(加入糖和牛奶)def customer_wants_condiments(self):answer input(咖啡要加糖和牛奶吗(y/n): )return answer.lower() yclass TeaMaker(BeverageMaker):茶制作def brew(self):print(用沸水浸泡茶叶)def add_condiments(self):print(加入柠檬)# 使用示例if __name__ __main__:print(制作咖啡:)coffee CoffeeMaker()coffee.make_beverage()print(\n *30 \n)print(制作茶:)tea TeaMaker()tea.make_beverage()模板方法模式的变体1. 带参数的模板方法实例class ConfigurableProcessor(ABC):可配置的数据处理器def process_with_config(self, input_file, output_file, config):带配置参数的模板方法self.validate_config(config)data self.read_data(input_file)processed_data self.process_with_config_impl(data, config)self.save_data(processed_data, output_file)self.post_process(config)def validate_config(self, config):验证配置 - 具体方法required_keys [format, encoding]for key in required_keys:if key not in config:raise ValueError(f配置中缺少必需的键: {key})abstractmethoddef process_with_config_impl(self, data, config):使用配置处理数据的实现passdef post_process(self, config):后处理 - 钩子方法if config.get(cleanup, False):print(执行清理操作)2. 多步骤模板方法实例class MultiStepProcessor(ABC):多步骤处理器def complex_processing(self):复杂处理流程self.initialize()self.pre_process()self.main_process()self.post_process()self.finalize()def initialize(self):print(初始化处理器)def pre_process(self):预处理 - 钩子方法passabstractmethoddef main_process(self):主要处理逻辑passdef post_process(self):后处理 - 钩子方法passdef finalize(self):print(处理完成)最佳实践和注意事项1. 合理使用抽象方法只将真正需要子类实现的方法声明为抽象方法为可选步骤提供默认实现的钩子方法2. 模板方法的访问控制模板方法通常应该声明为final在 Python 中可以通过命名约定步骤方法应该被保护避免外部直接调用3. 错误处理实例class RobustTemplate(ABC):健壮的模板类def template_method(self):try:self.setup()self.execute_steps()except Exception as e:self.handle_error(e)finally:self.cleanup()def execute_steps(self):执行步骤序列self.step1()self.step2()self.step3()def handle_error(self, error):错误处理 - 钩子方法print(f处理过程中发生错误: {error})abstractmethoddef setup(self):passabstractmethoddef step1(self):passabstractmethoddef step2(self):passabstractmethoddef step3(self):passdef cleanup(self):print(清理资源)实践练习现在轮到你来实践了请完成以下练习来巩固对模板方法模式的理解练习1实现文件导出模板创建一个文件导出模板支持导出为不同格式TXT、HTML、JSON。要求定义抽象基类FileExporter实现具体子类TXTExporter、HTMLExporter、JSONExporter模板方法应该包含准备数据、格式化数据、保存文件、后处理等步骤练习2改进饮料制作模板扩展之前的饮料制作模板添加以下功能支持选择饮料大小小杯、中杯、大杯添加价格计算功能支持自定义调料总结模板方法模式是一个强大而实用的设计模式它通过以下方式帮助我们构建更好的代码主要优点提高代码复用性将公共代码放在父类中提高扩展性通过子类扩展特定步骤符合开闭原则对扩展开放对修改关闭反向控制父类控制流程子类实现细节适用场景多个类有相同的方法但具体实现不同需要控制子类的扩展点需要定义算法骨架但允许某些步骤变化核心要点模板方法定义算法的不变部分抽象方法定义算法的可变部分钩子方法提供可选的扩展点❤️❤️❤️本人水平有限如有纰漏欢迎各位大佬评论批评指正如果觉得这篇文对你有帮助的话也请给个点赞、收藏下吧非常感谢! Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧

相关新闻