1、什么是模板模式?

模板方法模式(Template Method Pattern):定义一个操作中的算法的框架, 而将一些步骤延迟到子类中。 使得子类可以不改
变一个算法的结构即可重定义该算法的某些特定步骤。

说人话:父类模板方法定义不变的流程,子类重写流程中的方法。

2、模板模式定义

Java设计模式之(十三)——模板方法模式-LMLPHP

①、AbstractClass 抽象模板

一、基本方法

上面的 baseOperation() 或者 customOperation() 方法,也叫基本操作,是由子类实现的方法,并且在模板方法中被调用。

二、模板方法

上面的 templateMethod() 方法,可以有一个或者几个,实现对基本方法的调度,完成固定的逻辑。

②、ConcreteClass 具体模板

实现父类定义的一个或多个抽象方法,也就是父类定义的基本方法在子类中得以实现。

3、模板模式通用代码

public abstract class AbstractClass {
    // 共同的且繁琐的操作
    private void baseOperation() {
        // do something
    }

    // 由子类定制的操作
    protected abstract void customOperation();

    // 模板方法定义的框架
    public final void templateMethod() {
        /**
         * 调用基本方法,完成固定逻辑
         */
        baseOperation();
        customOperation();
    }

}
public class ConcreteClass1 extends AbstractClass{

    @Override
    protected void customOperation() {
        // 具体模板1 业务逻辑
        System.out.println("具体模板1:customOperation()");
    }
}
public class ConcreteClass2 extends AbstractClass{
    @Override
    protected void customOperation() {
        // 具体模板2 业务逻辑
        System.out.println("具体模板2:customOperation()");
    }
}

测试:

public class TemplateClient {
    public static void main(String[] args) {
        AbstractClass abstractClass1 = new ConcreteClass1();
        AbstractClass abstractClass2 = new ConcreteClass2();
        applyTemplate(abstractClass1);
        applyTemplate(abstractClass2);
    }

    public static void applyTemplate(AbstractClass abstractClass){
        abstractClass.templateMethod();
    }
}

4、模板模式优点

①、封装不变部分, 扩展可变部分

把认为是不变部分的算法封装到父类实现, 而可变部分的则可以通过继承来继续扩展。

②、提取公共部分代码, 便于维护

③、行为由父类控制, 子类实现

基本方法是由子类实现的, 因此子类可以通过扩展的方式增加相应的功能, 符合开闭原则。

5、模板模式缺点

①、子类执行的结果影响了父类的结果,这和我们平时设计习惯颠倒了,在复杂项目中,会带来阅读上的难度。

②、可能引起子类泛滥和为了继承而继承的问题

6、回调

为了解决模板模式的缺点,我们可以利用回调函数代替子类继承。

Java设计模式之(十三)——模板方法模式-LMLPHP
public interface Callback {
    void customOperation();
}
public class SubCallback implements Callback{
    @Override
    public void customOperation() {
        System.out.println("SubCallback customOperation");
    }
}
/**
 * 模板类
 * 声明为 final,无法被继承
 */
public final class Template {
    private void baseOperation(){
        System.out.println("模板类公共操作");
    }

    public void templateMethod(Callback callback){
        baseOperation();
        callback.customOperation();
    }
}

测试:

public class TemplateClient {
    public static void main(String[] args) {
        Template template = new Template();
        applyTemplate(template);
    }

    public static void applyTemplate(Template template){
        Callback callback = new SubCallback();
        template.templateMethod(callback);
    }
}

Template是一个稳定的final类,无法被继承,不存在子类行为影响父类结果的问题,而Callback是一个接口,为了继承而继承的问题消失了。

12-02 13:43