模板方法模式
模板方法模式(Template Method Pattern):简单说,模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤。
钩子方法
在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”。
案例描述
本例以制作”热饮“为例,现实生活中,大部分人可能喜欢喝开水、喝咖啡、喝茶等习惯,而制作这些的工序都大同小异,分为烧水、选配料、将开水倒入杯中、完工基本步骤。
UML类图关系
具体代码实现如下
HotDrink(热饮)
package com.lcq.Templatepattern;
/**
* @Author: coder
* @CreateTime: 2023-03-11
* @Description: 热饮
*/
public abstract class HotDrink {
//制作(模板方法)
public final void make() {//final修饰,防止子类覆盖,该算法一般固定
boilWater();//烧水
if (isAddCondiment()) {
addCondiment();//加配料
}
putToCup();//倒入杯中
finish();//完成
}
//烧水
public void boilWater() {
System.out.println("准备烧水");
}
//加配料
public abstract void addCondiment();
//倒入杯中
public void putToCup() {
System.out.println("开水倒入杯中");
}
//是否需要配料(钩子方法)
public boolean isAddCondiment() {
return true;
}
//制作完成
public abstract void finish();
}
Coffee(咖啡)
package com.lcq.Templatepattern;
/**
* @Author: coder
* @CreateTime: 2023-03-11
* @Description: 咖啡
*/
public class Coffee extends HotDrink{
private String condiment;
public Coffee(String condiment){
this.condiment = condiment;
}
@Override
public void addCondiment() {
System.out.println("加"+condiment);
}
@Override
public void finish() {
System.out.println(condiment+"咖啡制作完成");
}
}
BoilingWater(开水)
package com.lcq.Templatepattern;
/**
* @Author: coder
* @CreateTime: 2023-03-11
* @Description: 开水
*/
public class BoilingWater extends HotDrink{
@Override
public void addCondiment() {
}
@Override
public boolean isAddCondiment() {
return false;//开水,不加配料
}
@Override
public void finish() {
System.out.println("开水制作完成");
}
}
Tea(茶)
package com.lcq.Templatepattern;
/**
* @Author: coder
* @CreateTime: 2023-03-11
* @Description: 茶
*/
public class Tea extends HotDrink{
private String condiment;
public Tea(String condiment){
this.condiment = condiment;
}
@Override
public void addCondiment() {
System.out.println("加"+condiment);
}
@Override
public void finish() {
System.out.println(condiment+"茶制作完成");
}
}
Client
package com.lcq.Templatepattern;
/**
* @Author: coder
* @CreateTime: 2023-03-11
* @Description: TODO
*/
public class Client {
public static void main(String[] args) {
Coffee coffee = new Coffee("牛奶");
//开始制作牛奶咖啡
coffee.make();
System.out.println("---------------");
Tea tea = new Tea("龙井");
//开始制作龙井茶
tea.make();
System.out.println("---------------");
BoilingWater boilingWater = new BoilingWater();
//烧开水
boilingWater.make();
System.out.println("---------------");
}
}
运行结果
准备烧水
加牛奶
开水倒入杯中
牛奶咖啡制作完成
---------------
准备烧水
加龙井
开水倒入杯中
龙井茶制作完成
---------------
准备烧水
开水倒入杯中
开水制作完成
---------------
小结:模板方法负责定义算法框架,由子类实现差异化方法(抽象方法),钩子方法由子类主观判断是否需要覆盖。