模板模式
原理:在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中去实现
模板方法可以使得子类在不改变算法结构的情况下,重新定义算法中某一些步骤
结构
模板方法中的方法可以分为两类:模板方法和基本方法(基本方法又可以分为抽象方法、具体方法、钩子方法)
模板方法:一个模板方法是定义在抽象类中的,把基本方法组合在一起形成一个总算法或者总行为的方法
一个抽象类中可以有多个模板方法,每一个模板方法可以调用多个具体方法
模板方法一般设置成final,防止子类覆盖该算法的步骤
基本方法:
抽象方法:由子类具体的实现
具体方法:由抽象类声明并实现,子类并不实现或者置换
钩子方法:由抽象类声明并实现,而子类会加以扩展
举例
比如我们现在需要泡茶和泡咖啡
泡茶:将水煮沸-沸水煮茶-倒入杯中-判断是否加东西 -如果加东西则执行加东西的方法(加柠檬)
泡咖啡:将水煮沸-沸水煮咖啡-倒入杯中-判断是否加东西 -如果加东西则执行加东西的方法(加糖)
从这里我们可以提取出模板方法就是:五个步骤
基本方法就是实现的具体
抽象方法:沸水煮茶和沸水煮咖啡 如果加东西则执行加东西的方法(加柠檬)和如果加东西则执行加东西的方法(加糖)是抽象方法由子类实现
具体方法:将水煮沸和倒入杯中
钩子方法:判断是否加入东西(这里我们可以假设泡茶的时候加东西,泡咖啡不加东西)
代码示例
抽象类
public abstract class DreamMake {
//模板方法
public final void prepareDream(){
boilWater();
brew();
pourInCap();
if(isPutSomething())
addSomething();
}
//抽象方法
abstract void brew();
abstract void addSomething();
//具体方法
private void boilWater(){
System.out.println("将水煮沸");
}
//具体方法
private void pourInCap(){
System.out.println("倒入杯中");
}
//钩子方法:默认是加东西的这里要注意用public给子类用
public boolean isPutSomething(){
return true;
}
}
具体类(茶)
public class DreamTea extends DreamMake{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("沸水煮茶");
}
@Override
void addSomething() {
// TODO Auto-generated method stub
System.out.println("加柠檬");
}
}
具体类(咖啡)
public class DreamCafe extends DreamMake {
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("沸水煮咖啡");
}
@Override
void addSomething() {
// TODO Auto-generated method stub
System.out.println("加糖");
}
public boolean isPutSomething() {
// TODO Auto-generated method stub
return false;
}
}
客户端调用
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
DreamTea dreamTea = new DreamTea();
DreamCafe dreamCafe = new DreamCafe();
dreamTea.prepareDream();
System.out.println("\n");
dreamCafe.prepareDream();
}
}
运行结果
将水煮沸
沸水煮茶
倒入杯中
加柠檬
将水煮沸
沸水煮咖啡
倒入杯中
总结:
1.模板方法中把不变的行为搬移到超类中,减少子类代码的重复
2.子类实现某些细节有利于算法的扩展
3.策略模式和模板模式都是封装算法,前者使用组合委托模型,后者使用继承