模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern)
模板方法模式是一种行为设计模式,它定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
模式结构
- 抽象类(Abstract Class)
定义算法的骨架,并包含一个或多个抽象方法,供子类实现。抽象类还可以提供一些默认的实现。 - 具体类(Concrete Class)
实现抽象类中的抽象方法,完成算法中特定步骤的具体实现。
代码示例
1. 抽象类(Abstract Class)
// 房屋模板(抽象类)
abstract class HouseTemplate {
// 模板方法:定义算法的骨架
public final void build() {
buildFoundation();
buildPillars();
buildWalls();
buildWindows();
System.out.println("House is built.");
}
// 建造地基(默认实现)
private void buildFoundation() {
System.out.println("Building foundation with cement, iron rods and sand.");
}
// 建造窗户(默认实现)
private void buildWindows() {
System.out.println("Building Glass Windows.");
}
// 建造墙面(抽象方法,由子类实现)
public abstract void buildWalls();
// 建造支柱(抽象方法,由子类实现)
public abstract void buildPillars();
}
2. 具体类(Concrete Class)
// 木屋(具体类)
class WoodenHouse extends HouseTemplate {
@Override
public void buildWalls() {
System.out.println("Building Wooden Walls.");
}
@Override
public void buildPillars() {
System.out.println("Building Pillars with wood coating.");
}
}
// 玻璃屋(具体类)
class GlassHouse extends HouseTemplate {
@Override
public void buildWalls() {
System.out.println("Building Glass Walls.");
}
@Override
public void buildPillars() {
System.out.println("Building Pillars with glass coating.");
}
}
3. 调用示例
public class TemplateMethodPattern {
public static void main(String[] args) {
HouseTemplate houseTemplate = new WoodenHouse();
houseTemplate.build();
System.out.println("--------------------");
houseTemplate = new GlassHouse();
houseTemplate.build();
}
}
输出结果
Building foundation with cement, iron rods and sand.
Building Pillars with wood coating.
Building Wooden Walls.
Building Glass Windows.
House is built.
--------------------
Building foundation with cement, iron rods and sand.
Building Pillars with glass coating.
Building Glass Walls.
Building Glass Windows.
House is built.
应用场景
- 算法的骨架固定,部分步骤可变
当算法的整体结构固定,但某些步骤的实现可能不同时,可以使用模板方法模式。例如,房屋建造的流程固定,但墙面和支柱的材料可能不同。 - 避免代码重复
当多个类有相似的算法,但某些步骤的实现不同时,可以将公共部分提取到抽象类中,避免代码重复。 - 控制子类的扩展
当希望控制子类的扩展范围,只允许子类重写算法的某些特定步骤时,可以使用模板方法模式。
在Java中的应用
java.io.InputStream
和java.io.OutputStream
Java 的 I/O 流类中的非抽象方法(如read()
和write()
)使用了模板方法模式。子类可以重写特定的方法(如read(byte[] b, int off, int len)
)来改变行为。javax.servlet.http.HttpServlet
HttpServlet
类中的service()
方法是一个模板方法,它定义了处理 HTTP 请求的流程,但允许子类重写doGet()
、doPost()
等方法来处理具体的请求类型。
优缺点
优点
- 代码复用
模板方法模式将公共的算法逻辑提取到抽象类中,避免了代码重复。 - 扩展性
子类可以通过重写抽象方法来实现算法的特定步骤,而无需改变算法的整体结构。 - 控制子类行为
抽象类可以控制子类的扩展范围,确保算法的核心逻辑不被破坏。
缺点
- 灵活性受限
模板方法模式限制了子类的扩展范围,子类只能重写特定的步骤,不能改变算法的整体结构。 - 违反里氏替换原则
如果子类抑制了父类的默认实现,可能会导致违反里氏替换原则。 - 维护困难
如果模板方法中的步骤过多,可能会导致代码难以维护。
总结
模板方法模式通过定义一个算法的骨架,并将某些步骤延迟到子类中,使得子类可以在不改变算法结构的情况下重定义特定步骤。它适用于算法的整体结构固定,但某些步骤的实现可能不同的场景。尽管它可能会限制子类的灵活性,但其优点在于提高了代码的复用性和扩展性。在 Java 中,模板方法模式广泛应用于 I/O 流和 Servlet 等场景。