1.模版方法模式的定义
官方的一点的:定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。
通俗一点:就是把一些共用的操作(方法)抽象起来放到一个模版方法封装起来,可以在其子类里面重写相关的方法。
举个栗子理解:
就像生活中泡茶一样,某些步骤是一层不变的。比如第一步烧水,第二步放入茶叶,第三步记录一下时间,第四部要不要放枸杞~~~。可以把以上步骤方法抽象以后进行封装,子类继承后可以重写,泡茉莉花茶类就重写放入茶叶方法放入茉莉花,泡龙井茶类就重写放入茶叶方法放入龙井,以此类推。。。
2.写一个小小的案例
根据以上的情景写一个小demo
首先新建一个泡茶的抽象类,里面定义一个泡茶步骤的模版方法,以及各步骤的抽象方法。
/**
* @author lw
* @Title:
* @Description:模版方法抽象类
* @Version 1.0
*/
public abstract class AbstractMakeTeaTemplate {
/**
* @Author lw
* @Description //TODO模版方法,模版方法必须使用final修饰,防止被重写
* @Param []
* @return void
**/
public final void makeTeaTemplateMethod(){
//烧水
boilWater();
//放茶
putTea();
//记一下开始时间
recordBeginTime();
//记一下结束时间
recordEndTime();
//放枸杞(此处为钩子函数,默认为放枸杞,不想放可以在派生类中重写方法return false即可)
if(isAddChineseWolfberry()){
System.out.println("加一把枸杞补补!~~~~~");
}
}
//烧水方法
public abstract void boilWater();
//放茶到水中
public abstract void putTea();
//记录开始泡茶时间
public void recordBeginTime(){
System.out.println("开始泡茶时间:"+System.currentTimeMillis());
}
//记录结束泡茶时间
public void recordEndTime(){
System.out.println("结束泡茶时间:"+System.currentTimeMillis());
}
//是否加枸杞
public boolean isAddChineseWolfberry(){
return true;
};
}
注意点:1.模版方法一定使用final进行修饰,防止在派生类中被重写。2.可以定义一些钩子函数,通过重写来判断是否要执行模版方法中的某个步骤(就像抽象类中是否要加枸杞一样,默认是得加,可以在子类中重写return false,这样就不用加了~~~~)。
新建泡茉莉花茶类,继承AbstractMakeTeaTemplate抽象类
/**
* @author lw
* @Title:
* @Description:泡一杯茉莉花茶
* @Version 1.0
*/
public class MakeJasmineTea extends AbstractMakeTeaTemplate{
@Override
public void boilWater() {
System.out.println("家里有矿,烧一壶农夫三拳。。。");
}
@Override
public void putTea() {
System.out.println("放入一千块一两的茉莉花茶。。。");
}
}
新建泡龙井茶类,继承AbstractMakeTeaTemplate抽象类
/**
* @author lw
* @Title:
* @Description:泡一杯龙井茶
* @Version 1.0
*/
public class MakeLongJingTea extends AbstractMakeTeaTemplate{
@Override
public void boilWater() {
System.out.println("家境清寒,烧一壶自来水吧~~");
}
@Override
public void putTea() {
System.out.println("放入五块钱三包的过期龙井茶。。。。");
}
/**
* @Author lw
* @Description //TODO因为没钱,不加枸杞了,此处return false,可以覆盖父类的isAddChineseWolfberry方法
* @Param []
* @return boolean
**/
public boolean isAddChineseWolfberry(){
return false;
};
}
注意:这个类重写了是否加枸杞的方法,return false,在模版方法里面就不用执行
System.out.println("加一把枸杞补补!~~~~~");这句代码了
这个钩子可以根据实际情况灵活处理。
在main方法里面执行一下,
public class TemplateMethodMainTest {
public static void main(String[] args) {
AbstractMakeTeaTemplate amtt = new MakeJasmineTea();
amtt.makeTeaTemplateMethod();
System.out.println("--------------");
AbstractMakeTeaTemplate amtt1 = new MakeLongJingTea();
amtt1.makeTeaTemplateMethod();
}
}
看一下结果
3.模版方法模式的优缺点
优点:1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
4.画外篇~~
作为一个喜欢喝茶的程序员小菜鸡,安利一个不错的去处,河北张家口市蔚县茶山村,这地自驾游扎营贼爽,前两年自驾去过一次,风景巨好,真正融入大自然感觉,山好水好,回来的时候专门灌了几桶山泉水回来泡茶,一点渣滓都没有。在北京打拼/喜欢户外的同行可以去体验一下!(PS:带好保暖的装备,车技不好的童鞋不建议独自前往,高山草甸路不好走~~~)