概述
模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤,属于行为性设计模式。
适用于:
1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。
我们以炒菜为例子:
洗锅–>点火–>热锅–>上油–>下原料–>翻炒–>放调料–>出锅;
流程:
洗锅、点火、热锅、上油、翻炒、出锅都是一样的。
下原料和放调料是不一样的。
如果不使用模板模式:
炒菜接口:
public interface StirFry {
void washingPot();
void onFire();
void hotPot();
void pushOil();
void pushRawMaterial();
void Stir();
void pushSeasoning();
void outPot();
void stirFry();
}
//两个实现类:
public class StirPork implements StirFry{
@Override
public void washingPot() {
System.out.println("洗锅");
}
@Override
public void onFire() {
System.out.println("点火");
}
@Override
public void hotPot() {
System.out.println("热锅");
}
@Override
public void pushOil() {
System.out.println("放油");
}
@Override
public void pushRawMaterial() {
System.out.println("放原料猪肉");
}
@Override
public void Stir() {
System.out.println("翻炒");
}
@Override
public void pushSeasoning() {
System.out.println("放调料,盐,酱油");
}
@Override
public void outPot() {
System.out.println("出锅");
}
@Override
public void stirFry() {
washingPot();
onFire();
hotPot();
pushOil();
pushRawMaterial();
Stir();
pushSeasoning();
outPot();
}
}
public class StirSweetSourSpareribs implements StirFry{
@Override
public void washingPot() {
System.out.println("洗锅");
}
@Override
public void onFire() {
System.out.println("点火");
}
@Override
public void hotPot() {
System.out.println("热锅");
}
@Override
public void pushOil() {
System.out.println("放油");
}
@Override
public void pushRawMaterial() {
System.out.println("放原料排骨");
}
@Override
public void Stir() {
System.out.println("翻炒");
}
@Override
public void pushSeasoning() {
System.out.println("放调料,白砂糖,番茄酱、小苏打");
}
@Override
public void outPot() {
System.out.println("出锅");
}
@Override
public void stirFry() {
washingPot();
onFire();
hotPot();
pushOil();
pushRawMaterial();
Stir();
pushSeasoning();
outPot();
}
}
测试:
public class TestNoTemplate {
public static void main(String[] args) {
StirFry stirPork = new StirPork();
stirPork.stirFry();
System.out.println("====================================");
StirFry stirSweetSourSpareribs = new StirSweetSourSpareribs();
stirSweetSourSpareribs.stirFry();
}
}
结果:虽然成功,但是会出现大量重复代码。

此时使用模板方法模式,使用一个抽象类来进行相同的复用,把不同的流给子类自己实现:
接口:
public interface StirFry {
void washingPot();
void onFire();
void hotPot();
void pushOil();
void pushRawMaterial();
void Stir();
void pushSeasoning();
void outPot();
void stirFry();
}
抽象类:
public abstract class AbstractStirFry implements StirFry{
///复写那些相同的方法已达到复用,然后不同的流给子类自己实现
@Override
public void washingPot() {
System.out.println("洗锅");
}
@Override
public void onFire() {
System.out.println("点火");
}
@Override
public void hotPot() {
System.out.println("热锅");
}
@Override
public void pushOil() {
System.out.println("放油");
}
@Override
public void Stir() {
System.out.println("翻炒");
}
@Override
public void outPot() {
System.out.println("出锅");
}
@Override
public void stirFry() {
washingPot();
onFire();
hotPot();
pushOil();
pushRawMaterial();
Stir();
pushSeasoning();
outPot();
}
}
子类:
public class StirPork extends AbstractStirFry {
@Override
public void pushRawMaterial() {
System.out.println("放原料猪肉");
}
@Override
public void pushSeasoning() {
System.out.println("放调料,盐,酱油");
}
}
//甜酸排骨
//只需复写两个方法
public class StirSweetSourSpareribs extends AbstractStirFry {
@Override
public void pushRawMaterial() {
System.out.println("放原料排骨");
}
@Override
public void pushSeasoning() {
System.out.println("放调料,白砂糖,番茄酱、小苏打");
}
}
测试:
public class TestWithTemplate {
public static void main(String[] args) {
StirFry stirPork = new StirPork();
stirPork.stirFry();
System.out.println("====================================");
StirFry stirSweetSourSpareribs = new StirSweetSourSpareribs();
stirSweetSourSpareribs.stirFry();
}
}
结果:

减少了大量重复模板代码。但是这种模式下,不太建议子类复写抽象类已经复写了的方法,尽可能遵循里氏替换原则。
模板方法优缺点:
优点:
1、利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
2、将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
3、把不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,
符合开闭原则。
缺点:
1、类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
2、类数量的增加,间接地增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。





