news 2026/4/11 23:12:46

设计模式学习(15) 23-13 模版方法模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式学习(15) 23-13 模版方法模式

文章目录

  • 0.个人感悟
  • 1. 概念
  • 2. 适配场景
    • 2.1 适合的场景
    • 2.2 常见场景举例
  • 3. 实现方法
    • 3.1 实现思路
    • 3.2 UML类图
    • 3.3 代码示例
  • 4. 优缺点
    • 4.1 优点
    • 4.2 缺点
  • 5. 源码分析

0.个人感悟

  • 个人对这个模式印象很深,属于是工作中自己无意识地用到过,后面看书才发现原来已有前辈总结出这个模式,并且更加全面
  • 模版方法模式真的是很典型、很实用,建议大家可以在代码中尝试尝试
  • 模版方法整体是基于继承机制的代码复用,有利于感受抽象、封装、继承、多态的魅力
  • 模版方法模式很好地展现了开闭原则和实现开闭地一个方式: 将变化(具体实现)与不变的部分(算法骨架)分离

1. 概念

英文定义(《设计模式:可复用面向对象软件的基础》)

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without chaging the algorithm’s structure.

中文翻译

定义一个操作中的算法骨架,将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下重新定义算法的某些特定步骤。

理解

  • 模板方法模式是一种行为型设计模式
  • 父类(抽象类)定义了一个算法的固定框架和流程(模板方法)
  • 具体步骤的实现延迟到子类中完成
  • 子类可以重写某些特定步骤,但不能改变算法的整体结构
  • 通过钩子方法(Hook Method)提供额外的扩展点,允许子类对算法的某些部分进行可选的重写

2. 适配场景

2.1 适合的场景

  • 当多个类有相同的方法流程,但某些步骤的实现不同时,需要提取公共行为到父类,避免代码重复
  • 存在固定的算法骨架,但具体步骤需要灵活变化,需要控制子类的扩展方式,确保算法结构不被破坏

2.2 常见场景举例

  • 制作饮料:冲泡咖啡、茶的流程相似(烧水、冲泡、加调料),但具体步骤不同
  • 数据导入处理:读取数据、验证数据、处理数据、保存数据的流程固定,但不同数据源处理方式不同
  • Spring框架的JdbcTemplate:连接数据库、执行SQL、处理结果集、关闭连接的流程固定
  • 各种初始化流程:游戏初始化、应用启动、设备自检等有固定步骤但细节不同的场景

3. 实现方法

3.1 实现思路

  1. 创建抽象类:定义算法的骨架
  2. 定义模板方法:使用final修饰,防止子类改变算法结构
  3. 定义抽象方法:子类必须实现的具体步骤
  4. 定义具体方法:父类提供的默认实现,子类可选择是否重写
  5. 定义钩子方法:提供默认实现,子类可选择重写以影响算法流程
  6. 创建具体子类:实现抽象方法,可选重写钩子方法

3.2 UML类图

角色说明

  • AbstractClass(抽象类):定义模板方法和算法骨架
  • ConcreteClass(具体子类):实现抽象步骤,可选重写钩子方法

3.3 代码示例

制作饮料,冲泡咖啡、茶的流程相似(烧水、冲泡、加调料),但具体步骤不同
定义模版:

publicabstractclassBeverageTemplate{// 定义算法骨架 final防止子类篡改/** * @description 制作饮料 * @author bigHao * @date 2026/1/20 **/publicfinalvoidprepareBeverage(){boilWater();brew();pourInCup();if(customerWantsCondiments()){addCondiments();}hook();}// 通用流程/** * @description 烧水 * @author bigHao * @date 2026/1/20 **/privatevoidboilWater(){System.out.println("烧水");}// 通用流程/** * @description 倒饮料 * @author bigHao * @date 2026/1/20 **/privatevoidpourInCup(){System.out.println("将饮料倒入杯子");}// 特异流程,子类实现/** * @description 酿造 * @author bigHao * @date 2026/1/20 **/protectedabstractvoidbrew();// 特异流程,子类实现/** * @description 添加作料 * @author bigHao * @date 2026/1/20 **/protectedabstractvoidaddCondiments();// 钩子方法-子类可以重写,用于流程控制/** * @description 钩子方法 * @author bigHao * @date 2026/1/20 **/protectedvoidhook(){// 默认空实现}// 钩子方法,用于流程控制,子类可以重写/** * @return boolean 是否需要 * @description 客户需要作料 * @author bigHao * @date 2026/1/20 **/protectedbooleancustomerWantsCondiments(){returntrue;}}

具体实现:

publicclassCoffeeextendsBeverageTemplate{@Overrideprotectedvoidbrew(){System.out.println("沸水冲泡咖啡");}@OverrideprotectedvoidaddCondiments(){System.out.println("加入糖和牛奶");}@Overrideprotectedvoidhook(){super.hook();System.out.println("hook");}}publicclassTeaextendsBeverageTemplate{@Overrideprotectedvoidbrew(){System.out.println("沸水煮茶叶");}@OverrideprotectedvoidaddCondiments(){System.out.println("加入柠檬");}}

测试:

publicclassClient{staticvoidmain(){System.out.println("=== 制作coffee ===");BeverageTemplatecoffee=newCoffee();coffee.prepareBeverage();System.out.println("=== 制作tea ===");BeverageTemplatetea=newTea();tea.prepareBeverage();}}

输出:

=== 制作coffee === 烧水 用非税冲泡咖啡 将饮料倒入杯子 加入糖和牛奶 hook === 制作tea === 烧水 沸水煮茶叶 将饮料倒入杯子 加入柠檬

4. 优缺点

4.1 优点

  • 提高代码复用性:将公共行为提取到父类,避免代码重复
  • 良好的扩展性:通过增加新的子类可以轻松扩展算法
  • 符合开闭原则:对扩展开放(新增子类),对修改关闭(不修改模板方法)
  • 提高可维护性:算法结构清晰,便于理解和维护
  • 封装不变部分:将不变的行为封装在父类,可变行为由子类实现

4.2 缺点

  • 可能导致类数量增加:每个不同的实现都需要一个子类
  • 父类与子类耦合:子类必须实现父类的抽象方法
  • 限制了子类的灵活性:子类不能改变算法的整体结构
  • 继承的固有缺点:Java单继承限制,子类无法继承其他类
  • 调试困难:模板方法中的流程控制可能使调试变得复杂

5. 源码分析

Spring中的HttpServlet类service()方法分析

// javax.servlet.http.HttpServlet 中的模板方法模式应用publicabstractclassHttpServletextendsGenericServlet{// 模板方法protectedvoidservice(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{Stringmethod=req.getMethod();if(method.equals("GET")){// 调用具体方法doGet(req,resp);}elseif(method.equals("POST")){doPost(req,resp);}elseif(method.equals("PUT")){doPut(req,resp);}// ... 其他HTTP方法}// 钩子方法 - 子类需要实现具体处理逻辑protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{// 默认实现:返回405错误(方法不允许)resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);}protectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);}// ... 其他HTTP方法对应的钩子方法}

分析

  1. 模板方法service()方法定义了HTTP请求处理的整体流程
  2. 具体步骤:根据HTTP方法类型(GET、POST等)分发到不同的处理方法
  3. 钩子方法doGet()doPost()等由子类实现具体的业务逻辑
  4. 默认实现:父类提供错误响应的默认实现
  5. 扩展方式:开发者继承HttpServlet,只需重写需要处理的HTTP方法

使用示例

@WebServlet("/user")publicclassUserServletextendsHttpServlet{@OverrideprotectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{// 处理GET请求:查询用户信息// ...}@OverrideprotectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{// 处理POST请求:创建用户// ...}}

参考:

  • 韩顺平 Java设计模式
  • 张维鹏 Java设计模式之行为型:模板方法模式
  • java_my_life 《JAVA与模式》之模板方法模式
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/6 14:32:54

AI自动化智能体与工作流平台直播课

关注 霍格沃兹测试学院公众号,回复「资料」, 领取人工智能测试开发技术合集每天埋头于重复性工作,点击、复制、粘贴、测试,你是否感到时间被无形吞噬?当同事们早早下班,你是否还在为明天的汇报手动整理最后一份数据报告…

作者头像 李华
网站建设 2026/3/27 2:08:30

基于Python Selenium自动化测试的Jenkins持续集成项目搭建与实践

🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快Jenkins简介Jenkins是Java编写的非常流行的持续集成(CI)服务,起源于Hudson项目。所以Jenkins和Hudson功能相似。Jenkins支持各种…

作者头像 李华
网站建设 2026/4/8 10:31:50

深入解析CVE-2025-50341:Axelor SQL注入漏洞的技术细节与原理

项目标题与描述 CVE-2025-50341: Axelor SQL注入漏洞分析报告 本报告详细记录了在Axelor开源ERP/CRM平台v5.2.4版本中发现的SQL注入安全漏洞(CVE-2025-50341)。该漏洞允许攻击者通过应用程序的"_domain"参数实施布尔盲注攻击,从而逐…

作者头像 李华
网站建设 2026/4/12 2:48:48

广西北部湾,将成为未来最繁忙的航运地!

作为西部陆海新通道的关键枢纽,广西北部湾港已经迈入到了千万标箱的大港行列。 由钦州、北海、防城三大港口组成的北部湾港,正通过智能化、自动化转型升级,为这条国际大通道持续注入强劲动力。 2025年截至12月30日,班列开行量达…

作者头像 李华
网站建设 2026/4/12 6:56:00

13.3GB《ArcGIS Pro 地理信息系统应用与实践》配套练习数据

前段时间有朋友问,哪里有《ArcGIS Pro 地理信息系统应用与实践》这本书的配套练习数据? 其实,我们早前也买过这本书,但此书确实没有附光盘,也没有附上配套练习数据的下载地址。 当我们拿到这本书的之后,也…

作者头像 李华
网站建设 2026/4/7 9:22:59

伊朗离我们的距离,竟然比上海飞深圳还近!

提到伊朗,不少人觉得它是遥远中东的神秘国度,却不知它与中国的距离远比想象中更近。 中国新疆塔什库尔干县到伊朗最东边境仅1200多公里,比上海飞深圳的距离还要短。 当下的伊朗正面临内忧外患的动荡局势,但这份动荡从未蔓延至中…

作者头像 李华