定义
所谓模板方法模式就是在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法模式是基于继承的代码复用技术的。在模板方法模式中,我们可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中。也就是说我们需要声明一个抽象的父类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法让子类来实现剩余的逻辑,不同的子类可以以不同的方式来实现这些逻辑。
其实所谓模板就是一个方法,这个方法将算法的实现定义成了一组步骤,其中任何步骤都是可以抽象的,交由子类来负责实现。这样就可以保证算法的结构保持不变,同时由子类提供部分实现。
模板是一个方法,那么他与普通的方法存在什么不同呢?模板方法是定义在抽象类中,把基本操作方法组合在一起形成一个总算法或者一组步骤的方法。而普通的方法是实现各个步骤的方法,我们可以认为普通方法是模板方法的一个组成部分。
角色
- AbstractClass: 抽象类
- ConcreteClass: 具体子类
优缺点
优点
-
模板方法模式在定义了一组算法后,将具体的实现交由子类负责。
-
模板方法模式是一种代码复用的技术。
-
模板方法模式导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。
缺点
- 每一个不同的实现都需要一个子类来实现,导致类的个数增加使得系统更加庞大。
实例
以泡咖啡和泡茶为例,它们需要如下几步:
1) 烧开水
2) 将咖啡/茶叶放入杯中
3)将开水倒入杯中
模板抽象类:
public abstract class BrewingBeverage {
/**
* 添加咖啡/茶叶,具体逻辑由子类实现
*/
abstract void addCondiments();
/**
*
* @desc
* 模板方法,用来控制泡茶与冲咖啡的流程
* 申明为 final,不希望子类覆盖这个方法,防止更改流程的执行顺序
* @return void
*/
final void prepareRecipe(){
boilWater();
addCondiments();
pourInCup();
}
/**
* 烧水
*/
void boilWater(){
System.out.println("烧水");
}
/**
* 将水倒入杯中
*/
void pourInCup(){
System.out.println("将水倒入杯中");
}
}
具体实现类:
public class Tea extends BrewingBeverage {
@Override
void addCondiments() {
System.out.println("添加茶叶");
}
}
public class Coffee extends BrewingBeverage {
@Override
void addCondiments() {
System.out.println("添加咖啡");
}
}
调用:
public static void main(String[] args) {
Tea tea = new Tea();
tea.prepareRecipe();
Coffee coffee = new Coffee();
coffee.prepareRecipe();;
}
控制台输出:
烧水
添加茶叶
将水倒入杯中
烧水
添加咖啡
将水倒入杯中