模板模式

220 阅读2分钟

目的

固定一个操作算法的骨架,只允许子类重写实现细节,无法更改执行步骤。

定义

一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

结构

demo

不适用钩子

抽象模板

public abstract class Beverage {

    final void getBeverage() {
        boilingWater();
        make();
        pour();
        addFlavoring();
    }
    public void boilingWater() {
        System.out.println("烧水。。。");
    }

    public abstract void make();

    public void pour() {
        System.out.println("倒入杯中。。。。");
    }
    public abstract  void addFlavoring();
}

具体模板

public class Tea extends Beverage {
    @Override
    public void make() {
        System.out.println("把水倒入放有茶叶的杯中,盖上盖子");
    }

    @Override
    public void addFlavoring() {
        System.out.println("放入几片柠檬");
    }
}
public class Coffee extends Beverage {
    @Override
    public void make() {
        System.out.println("将水倒入装有coffee的杯中不断搅拌");
    }

    @Override
    public void addFlavoring() {
        System.out.println("加入 牛奶和糖");
    }
}

如上所示茶和coffee都是饮料,抽象模板中定义了制作饮料的具体步骤,并且将共同的实现步骤boilingWater和pour抽取到自身提高代码复用,而各种饮料特有的make和addFlavoring交由具体类自身选择实现。

使用钩子

抽象模板

public abstract class Beverage {

    final void getBeverage() {
        boilingWater();
        make();
        pour();
        addFlavoring();
    }
    public void boilingWater() {
        System.out.println("烧水。。。");
    }

    public abstract void make();

    public void pour() {
        if (pourPlace()) {
            System.out.println("倒入杯中。。。。");
        }

    }
    public abstract  void addFlavoring();
    public boolean pourPlace() {
        return true;
    }
}

具体模板

public class Tea extends Beverage {
    @Override
    public void make() {
        System.out.println("把水倒入放有茶叶的杯中,盖上盖子");
    }

    @Override
    public void addFlavoring() {
        System.out.println("放入几片柠檬");
    }
}
public class Coffee extends Beverage {
    @Override
    public void make() {
        System.out.println("将水倒入装有coffee的杯中不断搅拌");
    }

    @Override
    public void addFlavoring() {
        System.out.println("加入 牛奶和糖");
    }

    @Override
    public boolean pourPlace() {
        return false;
    }
}

client

public class Client {
    public static void main(String[] args) {
        Beverage beverage = new Tea();
        beverage.getBeverage();
        beverage = new Coffee();
        beverage.getBeverage();
    }
}

抽象模板中提供了一个钩子方法pourPlace决定是否将饮料倒入杯中,默认为true,子类可以重写该方法控制父类的行为,coffee重写返回false,所以如图所示coffee并没有倒入杯中,而茶使用父类的默认实现。

优点

约定算法执行步骤,提高代码复用性扩展性,实现了反向控制

缺点

引入抽象类,每一个不同的操作都需要具体子类实现,可能会出现类爆炸。。

使用时机

  • 需要控制算法执行步骤
  • 自身实现部分通用,可变的交由子类自身实现
  • 控制子类的扩展