JAVA设计模式——模板方法模式

模板方法模式是一种行为型设计模式。其思想是:将部分逻辑以具体方法的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑,不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现

模板方法模式涉及到2个角色:

  • 抽象模板(Abstract Template)
    • 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
    • 定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
  • 具体模板(Concrete Template)
    • 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。

结构图:
这里写图片描述

具体代码实现:

public abstract class AbstractTemplate {
    protected abstract void abstractMethod1();
    protected abstract void abstractMethod2();

    // 模板方法
    public final void templateMethod() {
        abstractMethod1();
        abstractMethod2();
    }
}

public class ConcreteTemplateA extends AbstractTemplate {

    @Override
    public void abstractMethod1() {
        System.out.println("method 1 A");
    }

    @Override
    public void abstractMethod2() {
        System.out.println("method 2 A");
    }
}

public class ConcreteTemplateB extends AbstractTemplate {

    @Override
    public void abstractMethod1() {
        System.out.println("method 1 B");
    }

    @Override
    public void abstractMethod2() {
        System.out.println("method 2 B");
    }
}

// 测试
class TemplateTest {
    public static void main(String[] args) {
        AbstractTemplate template = new ConcreteTemplateA();
        template.templateMethod();
    }
}

运行结果:

method 1 A
method 2 A

另外,模板中除了模板方法和抽象方法外,还有一种称为钩子的方法。钩子方法常常由抽象类给出一个空实现作为此方法的默认实现。这种空的钩子方法叫做“Do Nothing Hook”。显然,这种默认钩子方法与缺省适配模式的思路是一样的,这样具体模板类就不必实现所有的钩子,因为有些钩子其实是用不上的。钩子方法的命名应当以do开头,例如,在HttpServlet类中,doGet()doPost()等就是这样命名的。


这里,我们使用模板方法模式将策略模式帖子里例子再实现一遍。

// 抽象账单
public abstract class AbstractBill {
    protected double getTotal() {
        return 1000; // 模拟一个原始总价
    }
    protected abstract double cost(); // 此方法由具体模板实现

    // 模板方法:计算最后总价
    public final double finalBill() {
        return cost();
    }
}

// 非会员账单
public class CommonBill extends AbstractBill {
    @Override
    public double cost() {
        return getTotal(); // 原价
    }
}

// 会员账单
public class VipBill extends AbstractBill {
    @Override
    public double cost() {
        return getTotal()*0.88; // 88折
    }
}

public class Counter {
    private AbstractBill bill;

    public Counter(AbstractBill bill) {
        this.bill = bill;
    }

    public void showBill() {
        System.out.printf("the final bill costs %f\n", bill.finalBill());
    }
}

// 测试
class CounterTest {
    public static void main(String[] args) {
        // 模拟会员结账
        Counter counter = new Counter(new VipBill());
        counter.showBill();
    }
}

运行结果:

the final bill costs 880.000000

结构图:
这里写图片描述


可以看到,在策略模式的例子里,如果我们把抽象策略接口和提供公共方法抽象类二合为一,得到的代码结构与本例十分相似。但是,那并不是模板方法模式,因为当中并没有提供模板方法。

更多关于策略模式与模板方法模式的区别,可以参考这篇博文:
《模板方法模式、策略模式 的 联系、区别和应用场景》 - 赛艇队长 - 博客园

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值