文章目录

  • 一、类型
  • 二、定义
  • 三、参与者
  • 四、UML类图
  • 五、示例
  • 六、总结
  • 参考文章



一、类型

行为类模式


二、定义

定义一个算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。


三、参与者

1、AbstractClass抽象类:实现一个模板方法,定义算法的骨架,具体的子类将实现这些方法以实现算法的各个步骤;
2、ConcreteClass:具体的子类,实现抽象方法,以完成算法中的各个步骤。


四、UML类图

java 模型部署 java模型类_设计模式

说明:

  • AbstractClass 是抽象类,它有一个模板方法template(),定义了算法骨架,一般使用 final 进行修饰,防止子类重写模板方法;而 operation 就是具体的算法步骤,由子类来实现;
  • ConcreteClass 是实现类,它主要用于实现抽象类中具体的算法步骤。

五、示例

钩子方法:在模板方法模式的父类中,可以定义一个默认不做任何事的方法,子类视情况选择是否覆盖它。该方法就被成为钩子。

我们使用一个制作豆浆的例子来说明。
制作豆浆的步骤如下:选材->加豆子->加糖->浸泡并放入豆浆机打碎

  • 加豆子这个步骤,我们可以加黄豆或加红豆,我们将其做做成抽象方法,让子类去实现;
  • 加糖这个步骤,我们可以选择或不加,我们可以使用一个钩子方法来进行控制。

1、AbstractSoyaMilk:定义豆浆抽象类,定义了一个make模板方法,其定义了算法骨架即豆浆的制作流程;同时定义了一个钩子方法isAddSugar,子类可以进行覆盖,以决定是否加糖。

// 抽象类,表示豆浆的制作流程
public abstract class AbstractSoyaMilk {
    // 模板方法make,使用final修饰,防止子类覆盖
    final void make() {
        select();
        addBean();
        if (isAddSugar()) {
            addSugar();
        }
        beat();
    }

    // 第一步:选材
    void select() {
        System.out.println("选材");
    }

    // 第二步:添加豆子
    abstract void addBean();

    // 第三步:加糖
    void addSugar() {
        System.out.println("加糖");
    }

    // 第四步:浸泡并放入豆浆机
    void beat() {
        System.out.println("浸泡并放入豆浆机");
    }

    // 钩子方法,决定是否加糖
    boolean isAddSugar() {
        return true;
    }
}

2、RedBeanSoyaMildAbstractSoyaMilk抽象类的具体实现,定义方法addBean的具体实现

// 红豆豆浆
public class RedBeanSoyaMild extends AbstractSoyaMilk {
    @Override
    void addBean() {
        System.out.println("加入红豆");
    }
}

3、PeanutSoyaMildAbstractSoyaMilk抽象类的具体实现,定义addBean的具体实现;同时重写钩子方法isAddSugar

// 花生豆浆
public class PeanutSoyaMild extends AbstractSoyaMilk {
    @Override
    void addBean() {
        System.out.println("加入花生");
    }

    // 覆盖钩子方法,让其返回false,不加糖
    @Override
    boolean isAddSugar() {
        return false;
    }
}

4、Client:客户端

public class Client {
    public static void main(String[] args) {
        System.out.println(" 制作红豆豆浆 ");
        RedBeanSoyaMild redBeanSoyaMild = new RedBeanSoyaMild();
        redBeanSoyaMild.make();

        System.out.println(" 制作花生豆浆 ");
        PeanutSoyaMild peanutSoyaMild = new PeanutSoyaMild();
        peanutSoyaMild.make();
    }
}

执行结果:

制作红豆豆浆 
选材
加入红豆
加糖
浸泡并放入豆浆机
 制作花生豆浆 
选材
加入花生
浸泡并放入豆浆机

六、总结

1、基本思想
算法只存在于一个地方(即父类),容易修改。当需要修改算法时,只需要修改父类中的模板方法或已实现的某些步骤,子类就可直接继承这些修改。
2、优点和缺点
优点

  • 代码复用程度高、便于维护:父类的模板方法和某些步骤可以被子类所继承,因此也便于维护。
  • 统一了算法、易拓展:父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的具体实现。

缺点

  • 子类多:每一个不同的实现类都需要一个子类来实现,导致类的数量增多。

3、注意
一般会在模板方法上添加 final 关键字,防止子类重写模板方法。
4、使用场景
当要完成需执行一系列步骤的过程,这些步骤基本相同,但其个别步骤在实现时可能不同时,通常考虑模板方法模式来处理。