模板方法模式(Template Method)是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。
模板方法的结构
抽象模板(Abstract Template):定义了一个或多个抽象操作,以便让子类实现。逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
具体模板(Concrete Template):每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
模板模式的应用场景
- 一次性实现一个算法不变的部分,并将可变的行为留给子类实现。
- 各子类中公共的行为被提取出来并集中到一个公共父类中,从而避免代码的重复。
使用模板方法实现把大象装冰箱,拢共分几步
答案是:三步
- 把冰箱门打开。
- 把大象装进去。
- 把冰箱门带上。哈哈哈哈哈。。。。
首先,定义一个抽象模板类PutInRefrigerator,代码如下
public abstract class PutInRefrigerator {
protected final void createStep(){
this.openTheDoor();
if(checkRefrigerator()){
takeOut();
}
this.putInRefrigerator();
this.closeTheDoor();
}
protected boolean checkRefrigerator() {
return false;
}
final void takeOut(){
System.out.println("把冰箱里的东西拿出来!");
}
final void openTheDoor(){
System.out.println("打开冰箱门!");
}
abstract void putInRefrigerator();
final void closeTheDoor(){
System.out.println("把冰箱门带上!");
}
}
在PutInRefrigerator类中设定了创建的步骤,共有四步。其中包含一步检查冰箱内是否存在东西,如果有需要拿出来的步骤。设定放入冰箱的步骤为抽象方法,在子类中实现。
定义两个继承抽象类的子类,把大象装冰箱和把长颈鹿装冰箱两个类
public class PutElephantInRefrigerator extends PutInRefrigerator {
@Override
void putInRefrigerator() {
System.out.println("把大象放进去!");
}
}
public class PutGiraffeInRefrigerator extends PutInRefrigerator {
private boolean existence = false;
@Override
void putInRefrigerator() {
System.out.println("把长颈鹿放进去!");
}
public PutGiraffeInRefrigerator(boolean existence) {
this.existence = existence;
}
@Override
protected boolean checkRefrigerator() {
return this.existence;
}
}
在大象类中,只实现了把大象放冰箱。而在长颈鹿类中包含了设置检查冰箱的结果。
测试代码
public class Test {
public static void main(String[] args) {
System.out.println("把大象放冰箱要分几步");
PutInRefrigerator putInRefrigerator = new PutElephantInRefrigerator();
putInRefrigerator.createStep();
System.out.println("--------------------------------------");
System.out.println("把长颈鹿放冰箱要分几步");
PutInRefrigerator putInRefrigerator2 = new PutGiraffeInRefrigerator(true);
putInRefrigerator2.createStep();
}
}
结果如下
基本方法
基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。
- *抽象方法:*一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。
- *具体方法:*一个具体方法由抽象类声明并实现,而子类并不实现或置换。
- *钩子方法:*一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。
在上面的例子中,PutInRefrigerator是一个抽象类,它带有三个方法。其中putInRefrigerator()是一个抽象方法,它由抽象类声明为抽象方法,并由子类实现;checkRefrigerator()是一个钩子方法,它由抽象类声明并提供默认实现,并且由子类置换掉。openTheDoor()等是一个具体方法,它由抽象类声明并实现。
模板模式的优缺点
优点:
- 利用模板方法可以将相同处理逻辑放到抽象父类中,提高代码复用性。
- 将不同代码在子类中实现,也可以对子类扩展新的行为,提高代码扩展性。
缺点:
- 每个抽象类都需要子类实现,导致类个数增加,增加系统的复杂性。
- 集成关系的自身缺点,如果父类增加新抽象方法,所有子类都要修改。