介绍
**定义:**模板方法模式是一种基于继承的代码复用技术, 其结构只存在于父类和子类的继承关系中. 主要作用是提高程序的复用性(所有子类都可以复用父类中提供的模板方法代码)和拓展性(通过提供拓展点的方式使用户在不修改源码的前提下, 基于拓展点功能定制).
UML

示例
java
package com.sumlv.demo;
import com.sumlv.demo.templatemethod.AliPayTransfer;
import com.sumlv.demo.templatemethod.TransferTemplate;
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
TransferTemplate template = new AliPayTransfer();
template.handle("accountA", "accountB", new BigDecimal("1000.00"));
}
}
java
package com.sumlv.demo.templatemethod;
import java.math.BigDecimal;
/**
* 转账模板(抽象模板)
*
* @Auther: yuzhuo.song
* @Date: 2026-03-20
*/
public abstract class TransferTemplate {
/**
* 模板方法, 定义了整个逻辑的执行流程
*/
public void handle(String sourceAccount, String targetAccount, BigDecimal amount) {
if (this.validate(sourceAccount, targetAccount, amount)) {
try {
this.deductMoney(sourceAccount, amount);
BigDecimal serviceCharge = this.calculateServiceCharge(amount);
this.increaseMoney(targetAccount, amount.subtract(serviceCharge));
} catch (Exception e) {
// 此处省略回滚逻辑
}
}
}
/**
* 参数校验, 对于确定的逻辑可以直接在父类中实现
*/
protected boolean validate(String sourceAccount, String targetAccount, BigDecimal amount) {
return sourceAccount != null && targetAccount != null && amount != null;
}
/**
* 扣款, 对于确定的逻辑可以直接在父类中实现
*/
protected void deductMoney(String targetAccount, BigDecimal amount) {
// 此处省略转账方扣款逻辑.....
System.out.println("账户:" + targetAccount + "扣款:" + amount + "元");
}
/**
* 收款, 对于确定的逻辑可以直接在父类中实现
*/
protected void increaseMoney(String targetAccount, BigDecimal amount) {
// 此处省略收款方收款逻辑.....
System.out.println("账户:" + targetAccount + "增加:" + amount + "元");
}
/**
* 计算费率, 对于不确定的逻辑, 可以留到子类中实现
*/
protected abstract BigDecimal calculateServiceCharge(BigDecimal amount);
}
java
package com.sumlv.demo.templatemethod;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 微信转账
*
* @Auther: yuzhuo.song
* @Date: 2026-03-20
*/
public class WeChartTransfer extends TransferTemplate {
private static final BigDecimal RATE = new BigDecimal("0.002");
@Override
protected BigDecimal calculateServiceCharge(BigDecimal amount) {
BigDecimal serviceCharge = amount.multiply(RATE).setScale(2, RoundingMode.HALF_UP);
System.out.println("使用微信支付, 扣除手续费:" + serviceCharge + "元");
return serviceCharge;
}
/**
* 可以通过重写父类方法的方式调整模板方法的执行步骤
*/
@Override
protected boolean validate(String sourceAccount, String targetAccount, BigDecimal amount) {
return true;
}
}
java
package com.sumlv.demo.templatemethod;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 支付宝转账
*
* @Auther: yuzhuo.song
* @Date: 2026-03-20
*/
public class AliPayTransfer extends TransferTemplate {
private static final BigDecimal RATE = new BigDecimal("0.001");
@Override
protected BigDecimal calculateServiceCharge(BigDecimal amount) {
BigDecimal serviceCharge = amount.multiply(RATE).setScale(2, RoundingMode.HALF_UP);
System.out.println("使用支付宝支付, 扣除手续费:" + serviceCharge + "元");
return serviceCharge;
}
}
总结
使用场景
-
当多个类有相同的逻辑和方法可以执行时;
-
当业务逻辑/算法高度类似, 仅有部分差异需要定制时.
优点:
1.父类定义执行步骤子类负责实现执行细节的模式可以让开发者避免编写冗余代码而更加专注于不同逻辑;
-
通过子类重写父类方法的模式可以灵活的调整执行步骤, 从而达到无需修改父类代码即可实现反向控制的目的.
-
新增/更换子类实现方便, 符合单一职责和开闭原则.
缺点:
-
针对不同实现需要编写不同子类, 导致子类个数增加, 系统更加庞大;
-
子类反向控制父类执行顺序的方式提高了代码阅读和问题排查的难度.