一、定义
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
二、通用代码
- 抽象模板类
抽象模板类中的方法一般分为2种
- 基本方法(基本操作)
- 由子类实现的方法,并且在模板方法被调用
- 模板方法
- 可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调度,完成固定的逻辑
- 为防止恶意操作,一般加上final关键字,不允许被覆写
public abstract class AbstractClass{
//基本方法
protected abstract void doSomething();
//基本方法
protected abstract void doAnything();
//模板方法
public void templateMethod(){
/**
*调用基本方法,完成相关逻辑
**/
this.doAnything();
this.doSomething();
}
}
- 具体模板类
public class ConcreteClass1 extends AbstractClass{
protected void doSomething(){
//业务逻辑
}
protected void doAnything(){
//业务逻辑
}
}
public class ConcreteClass2 extends AbstractClass{
protected void doSomething(){
//业务逻辑
}
protected void doAnything(){
//业务逻辑
}
}
- 场景类
public class Client{
public static void main(String[] args){
AbstractClass class1 = new ConcreteClass1();
AbstractClass class2 = new ConcreteClass2();
//调用模板方法
class1.templateMethod();
class2.templateMethod();
}
}
三、优点
- 封装不变部分,扩展可变部分
- 将不变的部分封装到父类
- 将可变部分设为抽象方法,由子类继承扩展
- 提取公共部分代码,便于维护
- 行为由父类控制,子类实现
四、缺点
- 增加代码阅读难度
五、使用场景
- 多个子类有公有的方法,并且逻辑基本相同
- 重要、复杂的方法,可以把核心算法设计为模板方法,其他细节由子类实现
- 重构时,把相同的代码抽取到父类中,通过钩子函数约束其行为
六、扩展
- 钩子方法
- 由子类的一个方法返回值决定公共部分的执行结果