常用设计模式9:模板方法模式(Java)
模板方法模式(Template Method Pattern)
1. 简介
模板方法模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
2. 为什么使用模板方法模式?
- 代码复用:将公共代码放在抽象类中,避免重复。
- 扩展性:可以轻松地增加和修改算法步骤。
- 反向控制:父类调用子类的操作,而不是子类调用父类的操作。
- 遵循"好莱坞原则":不要调用我们,我们会调用你。
3. 模板方法模式的结构
模板方法模式主要包含以下角色:
- AbstractClass(抽象类):定义了一系列抽象操作,以及一个模板方法。
- ConcreteClass(具体类):实现抽象类中的抽象操作。
4. Java 实现示例
下面通过一个简单的饮料制作过程来说明模板方法模式:
4.1 定义抽象类
public abstract class Beverage {
// 模板方法
public final void prepareBeverage() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
// 抽象方法,由子类实现
abstract void brew();
abstract void addCondiments();
// 具体方法
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
// 钩子方法
boolean customerWantsCondiments() {
return true;
}
}
4.2 实现具体类
public class Coffee extends Beverage {
@Override
void brew() {
System.out.println("Dripping Coffee through filter");
}
@Override
void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
}
public class Tea extends Beverage {
@Override
void brew() {
System.out.println("Steeping the tea");
}
@Override
void addCondiments() {
System.out.println("Adding Lemon");
}
@Override
boolean customerWantsCondiments() {
return false; // 假设茶不需要调料
}
}
4.3 客户端代码
public class BeverageTestDrive {
public static void main(String[] args) {
Tea tea = new Tea();
Coffee coffee = new Coffee();
System.out.println("Making tea...");
tea.prepareBeverage();
System.out.println("\nMaking coffee...");
coffee.prepareBeverage();
}
}
5. 模板方法模式的优缺点
优点:
- 提高代码复用性
- 提供了一种反向控制结构
- 符合"开闭原则"
缺点:
- 每个不同的实现都需要一个子类,可能会导致类的数量增加
- 限制了算法的灵活性
6. 适用场景
- 当只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时。
- 当有多个类包含几乎相同的算法,但有一些细微的差异时。
7. 模板方法与策略模式的区别
虽然模板方法模式和策略模式都是处理算法变化的设计模式,但它们有以下区别:
- 继承 vs 组合:模板方法使用继承来改变部分算法,策略模式使用组合来改变整个算法。
- 算法结构:模板方法固定算法结构,策略模式允许完全替换算法。
- 控制反转:模板方法典型地使用"好莱坞原则",而策略模式通常不会。
8. Java 标准库中的模板方法
Java 标准库中有很多使用模板方法模式的例子:
java.io.InputStream
,java.io.OutputStream
,java.io.Reader
和java.io.Writer
的所有非抽象方法。java.util.AbstractList
,java.util.AbstractSet
和java.util.AbstractMap
的非抽象方法。
9. 总结
模板方法模式是一种简单但强大的设计模式,它通过将算法的结构定义在一个方法中,并将某些步骤的实现延迟到子类中,提供了一种灵活的方式来改变算法的部分实现。这种模式在框架设计中特别有用,因为它允许框架定义标准流程,同时允许用户通承来定制特定的步骤。然而,使用这种模式时需要注意避免创建过多的子类,并确保抽象类中的模板方法不会过于复杂。