定义
模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
简单来说模板方法定义了一套流程,流程中有哪些操作,操作的具体顺序是什么。而操作的具体实现则交给其子类去实现,模板方法不需要关心。
示例
现有需要对接支付宝和微信支付,部分方法是公用的,另外的需要不同的实现。这里可以使用模板方法,支付流程简单定义为
- 打开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元。
-----微信支付界面-----
密码输入中...
密码校验中...
微信支付结果:
支付失败!
可以看到,模板方法的优点是提升了代码的复用性和可拓展性。增加一种实现只需要增加一个子类,根据自己的业务去实现抽象方法即可。
缺点是后续的话类的数量可能会很多,不便于维护,如果修改了抽象类,可能需要修改的类数量很多。
总结
模板方法的核心思想
是:父类定义骨架
,子类实现
某些细节
。
参考资料
模板方法 (宝,我输液了,输的想你的夜)
模板方法 - 廖雪峰的官方网站
Q.E.D.