大话设计模式:模板方法模式

什么是模板方法?即让工作或流程顺序按照写好的模板进行下去,同时还可以自定义流程,以及简化流程。

举例:冲泡茶和咖啡均分四步进行:

  1. 把水煮沸
  2. 冲泡咖啡(茶)
  3. 把咖啡(茶)倒入杯子
  4. 加糖(柠檬)

一般写法

咖啡类

public class Coffee {

    public void prepare() {
        /**
         * 制作咖啡:
         * 1。 把水煮沸
         * 2。 用水冲泡
         * 3。 把咖啡倒进杯子
         * 4。 加糖
         */
        boilWater();
        brewCoffee();
        pourInCup();
        addSuger();
    }

    public void boilWater() {
        System.out.println("把水煮沸");
    }

    public void brewCoffee() {
        System.out.println("用水冲泡咖啡");
    }

    public void pourInCup() {
        System.out.println("把咖啡倒进杯子");
    }

    public void addSuger() {
        System.out.println("加糖");
    }

}

茶类

public class Tea {

    public void prepare() {
        /**
         * 制作茶:
         * 1。 把水煮沸
         * 2。 用水冲泡
         * 3。 把茶倒进杯子
         * 4。 加柠檬
         */
        boilWater();
        pourInCup();
        pourInCup();
        addLemon();
    }

    public void boilWater() {
        System.out.println("把水煮沸");
    }

    public void brewTea() {
        System.out.println("用水冲泡茶");
    }

    public void pourInCup() {
        System.out.println("把茶倒进杯子");
    }

    public void addLemon() {
        System.out.println("加柠檬");
    }

}

测试类

public class Test01 {

    /**
     * 这种实现方式有很多重复的代码
     */
    public static void main(String[] args) {
        Coffee coffee = new Coffee();
        Tea tea = new Tea();
        coffee.prepare();
        System.out.println("---------------");
        tea.prepare();
    }

}

模板方法

定义抽象的模板方法,把公共方法抽离出来,其它交给子类去实现

public abstract class DrinksTemplate {

    /**
     * 设定为final,不让子类去覆盖或篡改流程
     */
    final public void prepare() {
        boilWater();
        brew();
        pourInCup();
        add();
    }

    public void boilWater() {
        System.out.println("把水煮沸");
    }

    /**
     * 交给子类实现
     */
    public abstract void brew();

    public void pourInCup() {
        System.out.println("把饮料倒进杯子");
    }

    public abstract void add();

}

咖啡类

public class Coffee extends DrinksTemplate {

    @Override
    public void brew() {
        System.out.println("用沸水冲泡咖啡");
    }

    @Override
    public void add() {
        System.out.println("加糖");
    }
}

茶类

public class Tea extends DrinksTemplate {

    @Override
    public void brew() {
        System.out.println("用沸水冲泡茶");
    }

    @Override
    public void add() {
        System.out.println("加柠檬");
    }
}

测试类

public class Test01 {

    public static void main(String[] args) {
        Coffee coffee = new Coffee();
        Tea tea = new Tea();
        coffee.prepare();
        System.out.println("-----------");
        tea.prepare();
    }

}

使用钩子函数

钩子函数是在抽象模板方法中定义的,它的作用就是控制流程中的某个步骤是否执行、简化流程,子类可以选择覆盖。比如,在准备给用户冲泡咖啡或茶之前询问用户是否需要加糖或者柠檬,不需要就不进行加糖或柠檬这一步骤了。

抽象模板方法

public abstract class DrinksTemplate {

    /**
     * 设定为final,不让子类去覆盖或篡改流程
     */
    final public void prepare() {
        boilWater();
        brew();
        pourInCup();
        if (ifAdd()) {
            add();
        }
    }

    public void boilWater() {
        System.out.println("把水煮沸");
    }

    /**
     * 交给子类实现
     */
    public abstract void brew();

    public void pourInCup() {
        System.out.println("把饮料倒进杯子");
    }

    public abstract void add();

    /**
     * 钩子函数
     */
    public Boolean ifAdd() {
        return true;
    }

}

只让茶类去覆盖钩子函数

@Data
public class Tea extends DrinksTemplate {

    private Boolean ifAdd;

    @Override
    public void brew() {
        System.out.println("用沸水冲泡茶");
    }

    @Override
    public void add() {
        System.out.println("加柠檬");
    }

    @Override
    public Boolean ifAdd() {
        return ifAdd;
    }
}

测试类

@SuppressWarnings("Duplicates")
public class Test01 {

    public static void main(String[] args) {
        Coffee coffee = new Coffee();
        Tea tea = new Tea();
        // 启用钩子函数
        tea.setIfAdd(false);
        coffee.prepare();
        System.out.println("==========");
        tea.prepare();
    }

}

测试结果

把水煮沸
用沸水冲泡咖啡
把饮料倒进杯子
加糖
==========
把水煮沸
用沸水冲泡茶
把饮料倒进杯子
原文地址:https://www.cnblogs.com/zhangjianbing/p/13654891.html