定义
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
简单来说模板方法定义了一套流程,流程中有哪些操作,操作的具体顺序是什么。而操作的具体实现则交给其子类去实现,模板方法不需要关心。
示例
现有需要对接支付宝和微信支付,部分方法是公用的,另外的需要不同的实现。这里可以使用模板方法,支付流程简单定义为
- 打开 App
- 输入支付金额 (公用)
- 用户校验
- 显示支付结果
AbstractPaymentProcess
public abstract class AbstractPaymentProcess {
/**
* 支付流程
*/
public void pay(double amount) {
launchApp();
inputMoney(amount);
inputPassword();
faceId();
paymentResult();
}
/**
* 打开 App
*/
protected abstract void launchApp();
/**
* 输入支付金额
*
* @param amount 支付金额
*/
private final void inputMoney(double amount) {
System.out.println("当前待支付金额:" + amount + "元。");
}
/**
* 输入密码
*/
protected void inputPassword() {}
/**
* 面部识别支付
*/
protected void faceId() {}
/**
* 支付结果
*/
protected abstract void paymentResult();
}
打开 App 和显示支付结果为子类必须实现的方法,使用 abstract 修饰。 输入密码校验还是面部识别,选择一种实现即可,不定义为抽象方法。 输入支付金额为公用方法,已经内部实现。
WeChatPayment
public class WeChatPayment extends AbstractPaymentProcess {
@Override
protected void launchApp() {
System.out.println("打开微信");
}
@Override
protected void inputPassword() {
System.out.println("----- 微信支付界面 -----");
System.out.println("密码输入中...");
System.out.println("密码校验中...");
}
@Override
protected void paymentResult() {
boolean success = new Random().nextBoolean();
System.out.println("微信支付结果:");
if (success) {
System.out.println("支付成功!");
} else {
System.out.println("支付失败!");
}
}
}
AliPayment
public class AliPayment extends AbstractPaymentProcess {
@Override
protected void launchApp() {
System.out.println("打开支付宝");
}
@Override
protected void faceId() {
System.out.println("----- 支付宝界面 -----");
System.out.println("面容 ID 识别中...");
}
@Override
protected void paymentResult() {
boolean success = new Random().nextBoolean();
System.out.println("支付宝支付结果:");
if (success) {
System.out.println("支付成功!");
} else {
System.out.println("支付失败!");
}
}
}
TestTemplateMethod
@Test
public void test() {
AbstractPaymentProcess aliPay = new AliPayment();
aliPay.pay(12);
System.out.println("---------------------------------");
AbstractPaymentProcess weChatPay = new WeChatPayment();
weChatPay.pay(6);
}
输出结果
打开支付宝
当前待支付金额: 12.0 元。
----- 支付宝界面 -----
面容 ID 识别中...
支付宝支付结果:
支付成功!
---------------------------------
打开微信
当前待支付金额: 6.0 元。
----- 微信支付界面 -----
密码输入中...
密码校验中...
微信支付结果:
支付失败!
可以看到,模板方法的优点是提升了代码的复用性和可拓展性。增加一种实现只需要增加一个子类,根据自己的业务去实现抽象方法即可。 缺点是后续的话类的数量可能会很多,不便于维护,如果修改了抽象类,可能需要修改的类数量很多。
总结
模板方法的 核心思想
是:父类定义骨架
,子类实现
某些 细节
。