Featured image of post [设计模式] 模板方法

[设计模式] 模板方法

定义模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤

定义

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

简单来说模板方法定义了一套流程,流程中有哪些操作,操作的具体顺序是什么。而操作的具体实现则交给其子类去实现,模板方法不需要关心。

示例

现有需要对接支付宝和微信支付,部分方法是公用的,另外的需要不同的实现。这里可以使用模板方法,支付流程简单定义为

  • 打开 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 元。
----- 微信支付界面 -----
密码输入中...
密码校验中...
微信支付结果:
支付失败!

可以看到,模板方法的优点是提升了代码的复用性和可拓展性。增加一种实现只需要增加一个子类,根据自己的业务去实现抽象方法即可。 缺点是后续的话类的数量可能会很多,不便于维护,如果修改了抽象类,可能需要修改的类数量很多。

总结

模板方法的 核心思想 是:父类定义骨架子类实现 某些 细节

参考资料

模板方法 (宝,我输液了,输的想你的夜)
模板方法 - 廖雪峰的官方网站

使用 Hugo 构建 主题 StackJimmy 设计
发表了 32 篇文章・ 总计 66.22 k 字
本站总访问量 · 总访客数
本博客已稳定运行 🧡