面试知识库
高 基础

模板方法模式#

一句话答案#

父类定义算法骨架(abstract 方法),子类实现具体步骤,不改变算法结构;JdbcTemplate/RestTemplate 是典型。

核心要点

模板方法模式在父类中定义算法的骨架(执行流程),将某些步骤的实现延迟到子类。子类可以重新定义算法中的某些步骤,但不能改变算法的整体结构。

核心结构:

AQS 中的模板方法:

AbstractQueuedSynchronizer(AQS)是 Java 并发包的基础框架,典型的模板方法模式。→ 详见 AQS原理

AQS 定义了获取/释放锁的模板方法(不可重写),子类只需实现尝试获取/释放的方法:

AQS 子类实现的方法用途
ReentrantLock.SynctryAcquire / tryRelease可重入独占锁
Semaphore.SynctryAcquireShared / tryReleaseShared信号量
CountDownLatch.SynctryAcquireShared / tryReleaseShared倒计时门栓

Spring 中的模板方法:

  • JdbcTemplate:获取连接 → 执行 SQL(回调) → 释放资源
  • AbstractApplicationContext.refresh():Spring 容器启动的 12 步固定流程
  • RestTemplate:构建请求 → 执行请求 → 处理响应(Spring 6.1 起官方推荐用 RestClient 替代;Spring 团队计划在 Framework 7.1 将 RestTemplate 标记 @Deprecated(forRemoval)、8.0 移除)

注:JdbcTemplate/RestTemplate 这类 XxxTemplate 严格说是「模板方法 + 回调」的变体——骨架固定在模板类里,可变步骤通过传入回调对象(RowMapper、ResultSetExtractor 等)提供,而不是靠继承子类重写。

模板方法 vs 策略模式:

维度模板方法策略模式
实现方式继承(子类重写抽象方法)组合(传入不同策略对象)
算法完整性父类定义骨架,子类实现部分步骤策略类实现完整算法
灵活性编译期确定运行时可动态切换

面试回答(2分钟版)

模板方法模式的核心思想是在父类中用final方法定义算法骨架,把其中可变的步骤声明为abstract方法交给子类实现。这样算法的整体流程不变,但具体步骤可以定制。Java并发包中的AQS就是经典的模板方法:acquire()和release()是final的模板方法定义了获取释放锁的完整流程,而tryAcquire()和tryRelease()等方法由子类实现——注意它们不是abstract,AQS里默认抛UnsupportedOperationException,子类只需重写自己用到的那组:ReentrantLock实现独占模式的tryAcquire/tryRelease,Semaphore和CountDownLatch实现共享模式的tryAcquireShared/tryReleaseShared。Spring中也大量使用:JdbcTemplate封装了获取连接、执行SQL、释放资源的骨架,我们只需传入SQL和回调处理结果;AbstractApplicationContext的refresh()定义了容器启动的12步固定流程。模板方法还有一个钩子方法的概念,子类可以选择性覆盖来控制流程中的某些分支。和策略模式的区别在于模板方法通过继承在编译期确定,策略模式通过组合可以运行时动态切换。

追问与易错

追问方向:

  • “钩子方法是什么?”→ 父类中提供默认实现的方法,子类可以选择性覆盖来影响模板方法的执行流程(如控制某个步骤是否执行),是模板方法模式的扩展点
  • “和策略模式区别?”→ 模板方法通过继承在编译期确定,父类定义骨架子类实现部分步骤;策略模式通过组合在运行时动态切换,策略类实现完整算法且相互独立
  • “Spring 哪里用了模板方法?”→ JdbcTemplate(获取连接→执行 SQL→释放资源)、AbstractApplicationContext.refresh()(容器启动 12 步固定流程)、RestTemplate(构建请求→执行→处理响应)

易错点:

  • ❌ 模板方法灵活性差——钩子方法提供扩展点
  • ❌ AQS 的 tryAcquire 是抽象方法——它有默认实现(抛 UnsupportedOperationException),这样独占/共享子类只需实现各自需要的那组方法
  • ❌ JdbcTemplate 是靠继承实现的模板方法——它是「模板 + 回调」,可变步骤通过 RowMapper 等回调对象传入,用的是组合