介绍
定义了算法的固定步骤(不可改变),但是把这些步骤的具体实现内容交给子类来决定,模板方法模式提供了一种代码复用的重要技巧
示例demo
背景:朋友请客吃饭的固定流程(点菜下单 -> 烧饭 -> 吃饭 -> 买单 -> 娱乐)
请客吃饭:
/**
* 请客吃饭
* <p>
* 请客步骤
* 1、下单
* 2、烧饭
* 3、吃饭
* 4、买单
* 5、娱乐
**/
public abstract class Dinner {
/**
* 是否需要支付钱,默认是需要付钱的
*/
protected boolean isPay = true;
protected void order() {
System.out.println("点菜下单");
}
protected abstract void cooking();
protected abstract void eating();
/**
* 钩子方法,子类可以重写,控制是否需要付钱
*
* @param isPay
*/
protected void isPay(boolean isPay) {
this.isPay = isPay;
}
protected void payMoney() {
if (isPay) {
System.out.println("买单了");
}
}
protected void play() {
System.out.println("唱歌");
}
protected void dinner() {
// 1 下单
order();
// 2 烧饭
cooking();
// 3 吃饭
eating();
// 4 买单
payMoney();
// 5 娱乐
play();
}
}
请客吃火锅:
/**
* 请客吃火锅
**/
public class HotPot extends Dinner {
@Override
protected void cooking() {
System.out.println("火锅菜制作中");
}
@Override
protected void eating() {
System.out.println("火锅菜食用中");
}
@Override
protected void play(){
System.out.println("打牌");
}
}
请客吃牛排:
/**
* 请客吃牛排
**/
public class Steak extends Dinner {
@Override
protected void cooking() {
System.out.println("牛排制作中");
}
@Override
protected void eating() {
System.out.println("牛排食用中");
}
/**
* 重写钩子方法,由于是vip会员,所以不用付费
*
* @param isPay
*/
@Override
protected void isPay(boolean isPay){
this.isPay = isPay;
}
}
测试类:
public class TemplateTest {
@Test
public void hotPotTest() {
HotPot hotPot = new HotPot();
hotPot.dinner();
System.out.println("***************************");
}
@Test
public void steakTest() {
Steak steak = new Steak();
steak.isPay(false);
steak.dinner();
}
}
运行结果: