模板方法模式(Template Method Pattern) 是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的具体实现延迟到子类中。这种模式让子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
核心概念
-
抽象类(Abstract Class)
- 定义算法的骨架(模板方法),包含多个步骤的方法调用。
- 部分步骤方法可以是抽象的(由子类实现),也可以有默认实现。
-
具体子类(Concrete Subclass)
- 实现抽象类中的抽象方法,完成算法的特定步骤。
适用场景
- 多个子类有共同的算法结构,但部分步骤实现不同。
- 避免代码重复,将通用部分提取到父类,特殊部分由子类实现。
- 控制子类扩展点,只允许在特定步骤进行修改。
示例代码
假设我们要实现一个冲泡饮品的流程,包含烧水、冲泡、倒入杯子、添加配料四个步骤。其中“冲泡”和“添加配料”因饮品而异。
// 抽象类:定义冲泡饮品的模板
abstract class BeverageMaker {
// 模板方法:定义算法骨架,不可被重写
public final void prepareBeverage() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
// 通用步骤:默认实现
private void boilWater() {
System.out.println("烧开水");
}
// 抽象步骤:由子类实现
protected abstract void brew();
// 通用步骤:默认实现
private void pourInCup() {
System.out.println("倒入杯子");
}
// 抽象步骤:由子类实现
protected abstract void addCondiments();
// 钩子方法:子类可选择性覆盖
protected boolean customerWantsCondiments() {
return true;
}
}
// 具体子类:咖啡
class CoffeeMaker extends BeverageMaker {
@Override
protected void brew() {
System.out.println("用沸水冲泡咖啡");
}
@Override
protected void addCondiments() {
System.out.println("添加糖和牛奶");
}
}
// 具体子类:茶
class TeaMaker extends BeverageMaker {
@Override
protected void brew() {
System.out.println("用沸水浸泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("添加柠檬");
}
// 覆盖钩子方法,控制是否添加配料
@Override
protected boolean customerWantsCondiments() {
return false;
}
}
// 客户端代码
public class Main {
public static void main(String[] args) {
BeverageMaker coffee = new CoffeeMaker();
coffee.prepareBeverage();
System.out.println("\n=====\n");
BeverageMaker tea = new TeaMaker();
tea.prepareBeverage();
}
}
代码解释
-
抽象类
BeverageMaker
prepareBeverage()
:模板方法,定义了冲泡饮品的完整流程。brew()
和addCondiments()
:抽象方法,由子类实现。customerWantsCondiments()
:钩子方法(Hook Method),允许子类控制算法的某个步骤是否执行。
-
具体子类
CoffeeMaker
和TeaMaker
- 实现了
brew()
和addCondiments()
方法,定制饮品的冲泡和配料方式。 TeaMaker
覆盖了钩子方法,决定不添加配料。
- 实现了
优点
- 代码复用:将通用代码放在父类,避免子类重复实现。
- 算法统一控制:模板方法确保算法结构不变,子类只能修改特定步骤。
- 扩展性:子类可以灵活扩展或修改算法的特定部分。
缺点
- 子类数量可能过多:如果每个变体都需要一个子类,会导致类爆炸。
- 维护成本:如果模板方法过于复杂,修改父类可能影响所有子类。
实际应用
- JDK中的应用:
java.util.Collections
中的sort()
方法使用了模板方法模式,通过Comparator
接口让用户自定义排序规则。 - Servlet中的应用:
HttpServlet
中的doGet()
、doPost()
方法就是模板方法的扩展点。 - Spring框架:
JdbcTemplate
、HibernateTemplate
等模板类都使用了此模式。
注意事项
- 模板方法应声明为
final
:防止子类修改算法结构。 - 合理使用钩子方法:钩子方法可以让子类控制算法的某些步骤,增加灵活性。
通过模板方法模式,可以在父类中定义通用的算法框架,让子类专注于实现差异化的部分,从而提高代码的复用性和可维护性。
除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接
文章评论