李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 每日心情
  • Now
  • 系列文章
  • 论坛
  • 左邻右舍
    • 左邻右舍
    • 博友圈
  • 留言
    • 留言
    • 走心评论
  • 关于
    • 关于我
    • 网站地图
    • 网站统计
    • 另一个网站
    • 我的导航站
    • 赞助
  • 🚇开往
Destiny
自是人生长恨水长东
  1. 首页
  2. 后端
  3. 正文

Java设计模式:模板方法模式

2025年5月21日 约 1,036 字4 分钟 39 0 0
合集:Java设计模式第 3 篇 / 共 8 篇
Java›Java设计模式
  1. 1Java设计模式:状态模式
  2. 2Java设计模式:策略模式
  3. 3Java设计模式:模板方法模式当前
  4. 4JAVA设计模式-抽象工厂模式
  5. 5JAVA设计模式-工厂方法模式
  6. 6Java设计模式-原型模式
  7. 7Java设计模式-单例模式
  8. 8设计模式总结

模板方法模式(Template Method Pattern) 是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的具体实现延迟到子类中。这种模式让子类在不改变算法结构的情况下,重新定义算法中的某些步骤。

核心概念

  1. 抽象类(Abstract Class)

    • 定义算法的骨架(模板方法),包含多个步骤的方法调用。
    • 部分步骤方法可以是抽象的(由子类实现),也可以有默认实现。
  2. 具体子类(Concrete Subclass)

    • 实现抽象类中的抽象方法,完成算法的特定步骤。

适用场景

  • 多个子类有共同的算法结构,但部分步骤实现不同。
  • 避免代码重复,将通用部分提取到父类,特殊部分由子类实现。
  • 控制子类扩展点,只允许在特定步骤进行修改。

示例代码

假设我们要实现一个冲泡饮品的流程,包含烧水、冲泡、倒入杯子、添加配料四个步骤。其中“冲泡”和“添加配料”因饮品而异。

// 抽象类:定义冲泡饮品的模板
abstract class BeverageMaker {
    // 模板方法:定义算法骨架,不可被重写
    public final void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    // 通用步骤:默认实现
    private void boilWater() {
        System.out.println("烧开水");
    }

    // 抽象步骤:由子类实现
    protected abstract void brew();

    // 通用步骤:默认实现
    private void pourInCup() {
        System.out.println("倒入杯子");
    }

    // 抽象步骤:由子类实现
    protected abstract void addCondiments();

    // 钩子方法:子类可选择性覆盖
    protected boolean customerWantsCondiments() {
        return true;
    }
}

// 具体子类:咖啡
class CoffeeMaker extends BeverageMaker {
    @Override
    protected void brew() {
        System.out.println("用沸水冲泡咖啡");
    }

    @Override
    protected void addCondiments() {
        System.out.println("添加糖和牛奶");
    }
}

// 具体子类:茶
class TeaMaker extends BeverageMaker {
    @Override
    protected void brew() {
        System.out.println("用沸水浸泡茶叶");
    }

    @Override
    protected void addCondiments() {
        System.out.println("添加柠檬");
    }

    // 覆盖钩子方法,控制是否添加配料
    @Override
    protected boolean customerWantsCondiments() {
        return false;
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        BeverageMaker coffee = new CoffeeMaker();
        coffee.prepareBeverage();

        System.out.println("\n=====\n");

        BeverageMaker tea = new TeaMaker();
        tea.prepareBeverage();
    }
}

代码解释

  1. 抽象类 BeverageMaker

    • prepareBeverage():模板方法,定义了冲泡饮品的完整流程。
    • brew() 和 addCondiments():抽象方法,由子类实现。
    • customerWantsCondiments():钩子方法(Hook Method),允许子类控制算法的某个步骤是否执行。
  2. 具体子类 CoffeeMaker 和 TeaMaker

    • 实现了 brew() 和 addCondiments() 方法,定制饮品的冲泡和配料方式。
    • TeaMaker 覆盖了钩子方法,决定不添加配料。

优点

  • 代码复用:将通用代码放在父类,避免子类重复实现。
  • 算法统一控制:模板方法确保算法结构不变,子类只能修改特定步骤。
  • 扩展性:子类可以灵活扩展或修改算法的特定部分。

缺点

  • 子类数量可能过多:如果每个变体都需要一个子类,会导致类爆炸。
  • 维护成本:如果模板方法过于复杂,修改父类可能影响所有子类。

实际应用

  • JDK中的应用:java.util.Collections 中的 sort() 方法使用了模板方法模式,通过 Comparator 接口让用户自定义排序规则。
  • Servlet中的应用:HttpServlet 中的 doGet()、doPost() 方法就是模板方法的扩展点。
  • Spring框架:JdbcTemplate、HibernateTemplate 等模板类都使用了此模式。

注意事项

  • 模板方法应声明为 final:防止子类修改算法结构。
  • 合理使用钩子方法:钩子方法可以让子类控制算法的某些步骤,增加灵活性。

通过模板方法模式,可以在父类中定义通用的算法框架,让子类专注于实现差异化的部分,从而提高代码的复用性和可维护性。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/hou-duan/4416

推荐阅读

  • Java设计模式:状态模式
  • Java设计模式:策略模式
  • JAVA设计模式-抽象工厂模式
  • JAVA设计模式-工厂方法模式
  • Java设计模式-原型模式
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: JAVA 模板方法模式 设计模式
最后更新:2026年7月14日
相关文章
  • SpringBoot整合GraphQL入门教程2022年1月28日
  • SpringBoot使用RestTemplate进行接口调用2021年1月19日
  • OHCache使用2022年9月22日
  • Java SPI详解2021年4月16日
  • Java设计模式:状态模式2025年5月22日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 合集上一篇
合集下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复

文章评论

还没有评论,快来抢沙发吧~

Your time is limited, so don't waste it living someone else's life. Don't be trapped by dogma -- which is living with the results of other people's thinking. Don't let the noise of other's opinions drown out your own inner voice. And most important, have the courage to follow your heart and intuition. They somehow already know what you truly want to become. Everything else is secondary.

听点儿音乐吧 朋友~
文章目录
最新 热点 随机
最新 热点 随机
每日早报 · 2026年8月18日 写了一个订阅每日新闻的WP插件 每日早报 · 2026年8月17日 每日早报 · 2026年8月16日 每日早报 · 2026年8月15日 每日早报 · 2026年8月14日
给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能Kratos+ v1.1.16版本更新说明AI时代,个人技术博客的出路在哪里?增加了两套复古皮肤-牛皮纸、千禧网页这个域名注册整整十年了,十年时间,真快啊Kratos+ v1.1.14版本更新说明
CC知识共享协议各协议内容解释 深度解析多级缓存架构:从设计到落地,彻底解决数据一致性难题 从零开始入门 K8s | Kubernetes 网络概念及策略控制 AI原生数据库新标杆:seekdb深度解析,轻量架构与混合搜索的双重革命 结合Apollo配置中心实现日志级别动态配置 使用RocketMQ时,服务启动过程中,Consumer在服务未启动时消费消息问题处理
最近评论
李锋镝 发布于 3 小时前(08月18日) 给主题加了个功能,可以在RSS中排除指定分类,哈哈哈
李锋镝 发布于 4 小时前(08月18日) :8: 喜欢就好
不凡 发布于 14 小时前(08月17日) 哇,配色真好看,观感很舒服! :52:
李锋镝 发布于 17 小时前(08月17日) 哈哈哈,那个插件我之前也用过,那个内容都是固定的,我这个每天不同的时间拉取数据也不一样,等我研究研究...
Hary 发布于 17 小时前(08月17日) emmm大哥,这样每天输出到博客,然后别人订阅rss全是这个,有点不太好,之前很流行一段时间每天60...
标签聚合
Redis MQ JVM MySQL 多线程 ElasticSearch 日常 Claude IDEA AI 分布式 SpringBoot SQL AI编程 K8s 数据库 WordPress JAVA 架构 Spring
友情链接
  • 瓦匠个人小站
  • 若梦博客
  • 九仞之行
  • 老张博客
  • 知向前端
  • 哥斯拉
  • Honesty
  • 韩情脉脉
  • 皮皮社
  • Serendipity
  • Mr.Sun的博客
  • 韩小韩博客
  • 志文工作室
  • 懋和道人
  • 临窗旋墨
  • 搬砖日记
  • 林羽凡
  • 彬红茶日记
  • 蜗牛工作室
  • sssr7844的博客

COPYRIGHT © 2026 lifengdi.com. ALL RIGHTS RESERVED.

正在博友圈履约中

域名年龄

Theme Kratos+ By Dylan Li

津ICP备2024022503号-3

京公网安备11011502039375号