[设计模式] - 模板方法 把大象放冰箱,拢共分几步?

模板方法模式(Template Method)是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。

模板方法的结构

抽象模板(Abstract Template):定义了一个或多个抽象操作,以便让子类实现。逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。*逻辑也有可能调用一些具体方法。
具体模板(Concrete Template):每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是*逻辑的组成步骤)的不同实现,从而使得*逻辑的实现各不相同。

模板模式的应用场景

  • 一次性实现一个算法不变的部分,并将可变的行为留给子类实现。
  • 各子类中公共的行为被提取出来并集中到一个公共父类中,从而避免代码的重复。

使用模板方法实现把大象装冰箱,拢共分几步

答案是:三步

  1. 把冰箱门打开。
  2. 把大象装进去。
  3. 把冰箱门带上。哈哈哈哈哈。。。。

首先,定义一个抽象模板类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()等是一个具体方法,它由抽象类声明并实现。

模板模式的优缺点

优点:

  1. 利用模板方法可以将相同处理逻辑放到抽象父类中,提高代码复用性。
  2. 将不同代码在子类中实现,也可以对子类扩展新的行为,提高代码扩展性。

缺点:

  1. 每个抽象类都需要子类实现,导致类个数增加,增加系统的复杂性。
  2. 集成关系的自身缺点,如果父类增加新抽象方法,所有子类都要修改。