定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类当中。使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
/** 为了防止恶意的操作,一般模板方法都加上final关键字,不允许被覆写。 */
// 抽象模板类
public abstract class AbstractClass{
// 基本方法
protected abstract void doSomething();
// 基本放法
protected abstract void doAnything();
// 模板方法
public void templateMethod(){
/*
* 调用基本方法,完成算法逻辑
*/
this.doAnything();
this.doSomething();
}
}
// 具体模板类1
public class ConcreteClass1 extends AbstractClass{
// 实现基本方法
protected void doSomething(){
// 业务逻辑处理
}
protected void doAnything(){
// 业务逻辑处理
}
}
// 具体模板类2
public class ConcreteClass2 extends AbstractClass{
// 实现基本方法
protected void doSomething(){
// 业务逻辑处理
}
protected void doAnything(){
// 业务逻辑处理
}
}
// 场景类
public class Client{
public static void main(Stirng[] args){
AbstractClass clazz1 = new ConcreteClass1();
AbstractClass clazz2 = new ConcreteClass2();
// 调用模板方法
clazz1.templateMethod();
clazz2.templateMethod();
}
}
/ ** 抽象模板类中的基本方法尽量设置为protected类型,符合LoD,不需要暴露的属性或者方法尽量不要设置为protected类型。实现类若非必要,尽量不要扩大父类中的访问权限 */
- 模板方法模式的优点
- 封装不变部分,扩展可变部分;
- 提取公共部分代码,便于维护;
- 行为由父类控制,子类实现。
- 模板方法模式的缺点
- 抽象类定义了部分抽象方法,由子类实现,子类的执行结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度。
- 模板方法模式的使用场景
- 多个子类有公有的方法,并且逻辑基本相同时;
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现;
- 重构时,模板方法是一个经常使用的模式,把相同代码抽取到父类当中,然后通过"钩子函数"约束其行为。
- 模板方法模式的扩展
- “钩子方法”:在抽象父类中定义protect方法(钩子函数),并在模板方法中使用该方法的返回值约束方法行为,然后在具体实现子类中覆写该方法,便可实现具体子类对模板方法中的行为约束。
个人理解:
把不变流程的钉死(final),把可变的抽象(abstract),就是模板方法模式。
泡饮品一共四部:烧水 → 冲泡 → 加料 → 端杯,
其中 冲泡、加料 是可变的,冲咖啡就是咖啡、冲奶茶就是奶茶,咖啡加牛奶、奶茶加椰果。