Java 设计模式之模板模式
一、定义
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
主要角色:
抽象类:负责给出一个算法的轮廓或骨架,它由一个模板方法和若干个基本方法构成。
模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
具体方法:是实现算法各个步骤的方法,是模板方法的组成部分,基本方法又分为三种:
抽象方法:一个抽象方法由抽象类声明,由具体子类实现
具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
具体子类:实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤。
二、代码实现
举例:例如去银行办理业务,需要取号,排队,办理具体业务,对工作人员评分,其中取号,排队,评分三个步骤不论是谁都是一样的,但是办理具体业务却因人而异,可能是存款,可能是取款,可以延迟到子类中实现。
抽象类:
public abstract class AbstractClass { //模板方法 public void start(){ getNumber(); lineUp(); doSomething(); appraise(); } //基本方法 public void getNumber(){ System.out.println("银行取号"); } public void lineUp(){ System.out.println("银行排队"); } public void appraise(){ System.out.println("银行评价"); } //抽象方法 public abstract void doSomething(); }
具体子类:办理存款业务
public class Deposit extends AbstractClass { @Override public void doSomething() { System.out.println("办理存款业务"); } }
使用:
public static void main(String[] args) { Deposit deposit = new Deposit(); deposit.start(); }
输出:
银行取号 银行排队 办理存款业务 银行评价
如果此时想要办理取款业务怎么办?那么只需要增加一个子类来完成具体的取款业务:
具体子类:办理取款业务
public class Withdraw extends AbstractClass { @Override public void doSomething() { System.out.println("办理取款业务"); } }
三、总结
优点:提高代码的复用性,将相同部分放在抽象的父类中,不同的代码放入不同的子类中。
缺点:对于每一个不同的实现都需要定义一个子类,导致类的数量增加。
场景:算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,由子类实现。或需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。