0128_模板方法(Template Method)
模板方法(Template Method)
意图
定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法结构的情况下,重新定义算法中的某些特定步骤。
UML 图

优点
- 代码复用:将公共行为移到父类中,避免代码重复
- 封装不变部分:固定算法结构,保护核心算法不被修改
- 扩展性好:通过子类扩展具体实现,符合开闭原则
- 便于维护:算法修改只需在父类中进行,子类不受影响
- 提高灵活性:子类可以灵活实现特定步骤,而不影响整体结构
缺点
- 限制扩展性:算法框架固定,可能限制子类的灵活性
- 增加系统复杂度:每个不同实现都需要一个子类,可能导致类数量增加
- 违反里氏替换原则:如果子类对模板方法进行重写,可能破坏父类定义的行为
- 调试困难:模板方法中的步骤调用可能在多个子类中实现,调试较复杂
- 可能产生过多抽象:如果步骤划分过细,可能导致系统过于抽象
代码示例
以人类和机器人执行任务的不同方式为例:
1. 抽象模板类 (Abstract Template Class)
// 抽象任务模板
public abstract class TaskTemplate {
private String taskName;
public TaskTemplate(String taskName) {
this.taskName = taskName;
}
// 模板方法 - 定义算法骨架 (final防止子类重写)
public final void executeTask() {
System.out.println("🚀 开始执行任务: " + taskName);
prepareEnvironment();
performCoreTask();
cleanup();
generateReport();
System.out.println("✅ 任务完成: " + taskName + "\n");
}
// 具体方法 - 通用实现
private void prepareEnvironment() {
System.out.println("🔧 准备执行环境...");
}
// 抽象方法 - 由子类实现
protected abstract void performCoreTask();
// 钩子方法 - 默认实现,子类可选择重写
protected void cleanup() {
System.out.println("🧹 执行默认清理操作...");
}
// 具体方法 - 通用实现
private void generateReport() {
System.out.println("📊 生成任务报告...");
}
public String getTaskName() {
return taskName;
}
}
2. 具体实现类 (Concrete Implementations)
// 人类任务执行者
public class HumanTaskExecutor extends TaskTemplate {
public HumanTaskExecutor(String taskName) {
super(taskName);
}
@Override
protected void performCoreTask() {
System.out.println("👤 人类正在执行任务:");
System.out.println(" 💡 运用创造力和直觉");
System.out.println(" 🤝 进行团队协作");
System.out.println(" ❤️ 融入情感因素");
}
@Override
protected void cleanup() {
System.out.println("🧽 人类进行细致的手工清理...");
}
}
// 机器人任务执行者
public class RobotTaskExecutor extends TaskTemplate {
public RobotTaskExecutor(String taskName) {
super(taskName);
}
@Override
protected void performCoreTask() {
System.out.println("🤖 机器人正在执行任务:");
System.out.println(" ⚡ 高速精确计算");
System.out.println(" 📏 严格按照程序执行");
System.out.println(" 🔄 重复性工作无误差");
}
@Override
protected void cleanup() {
System.out.println("🛠️ 机器人进行自动化清理...");
}
}
// 混合任务执行者 - 展示钩子方法的使用
public class HybridTaskExecutor extends TaskTemplate {
private boolean needsSpecialCleanup;
public HybridTaskExecutor(String taskName, boolean needsSpecialCleanup) {
super(taskName);
this.needsSpecialCleanup = needsSpecialCleanup;
}
@Override
protected void performCoreTask() {
System.out.println("👥 人机协作执行任务:");
System.out.println(" 🧠 人类负责决策和创意");
System.out.println(" 💻 机器人负责计算和执行");
System.out.println(" 🤝 完美协作完成任务");
}
@Override
protected void cleanup() {
if (needsSpecialCleanup) {
System.out.println("🌟 执行特殊的协作清理流程...");
} else {
super.cleanup(); // 使用父类的默认实现
}
}
}
3. 客户端代码
public class TemplateMethodDemo {
public static void main(String[] args) {
System.out.println("=== 模板方法模式演示 ===\n");
// 创建不同类型的任务执行者
TaskTemplate humanTask = new HumanTaskExecutor("创意设计任务");
TaskTemplate robotTask = new RobotTaskExecutor("数据分析任务");
TaskTemplate hybridTask1 = new HybridTaskExecutor("复杂项目任务", false);
TaskTemplate hybridTask2 = new HybridTaskExecutor("敏感数据处理任务", true);
// 执行任务 - 相同的模板方法,不同的具体实现
System.out.println("1. 人类执行任务:");
humanTask.executeTask();
System.out.println("2. 机器人执行任务:");
robotTask.executeTask();
System.out.println("3. 人机协作任务 (默认清理):");
hybridTask1.executeTask();
System.out.println("4. 人机协作任务 (特殊清理):");
hybridTask2.executeTask();
// 演示模板方法的灵活性
System.out.println("=== 动态任务执行 ===");
TaskTemplate[] tasks = {
new HumanTaskExecutor("紧急创意任务"),
new RobotTaskExecutor("批量处理任务"),
new HybridTaskExecutor("综合解决方案", true)
};
for (TaskTemplate task : tasks) {
task.executeTask();
}
}
}
在Java标准库中的应用
模板方法模式在Java标准库中的广泛应用:
- InputStream/OutputStream
// InputStream 中的模板方法
public abstract class InputStream {
// 模板方法
public int read(byte[] b, int off, int len) throws IOException {
// ... 算法骨架
int c = read(); // 调用抽象方法
// ... 后续处理
return c;
}
// 抽象方法 - 由子类实现
public abstract int read() throws IOException;
}
- AbstractList/AbstractSet
// AbstractList 中的模板方法
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
// 模板方法
public boolean addAll(int index, Collection<? extends E> c) {
// ... 算法骨架
for (E e : c) {
add(index++, e); // 调用抽象方法
}
return true;
}
// 抽象方法 - 由子类实现
public abstract void add(int index, E element);
}
- HttpServlet
// HttpServlet 中的模板方法
public abstract class HttpServlet extends GenericServlet {
// 模板方法
protected void service(HttpServletRequest req, HttpServletResponse resp) {
String method = req.getMethod();
if (method.equals("GET")) {
doGet(req, resp); // 调用具体方法
} else if (method.equals("POST")) {
doPost(req, resp); // 调用具体方法
}
// ... 其他HTTP方法
}
// 由子类实现的具体方法
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
// 默认实现
}
}
- Java AWT/Swing
// JComponent 中的绘制模板
public abstract class JComponent extends Container {
// 模板方法
public void paint(Graphics g) {
paintComponent(g); // 由子类实现
paintBorder(g); // 默认实现
paintChildren(g); // 默认实现
}
// 抽象方法 - 由子类实现
protected void paintComponent(Graphics g);
}
总结
模板方法模式通过定义算法的骨架而将一些步骤延迟到子类中,实现了代码复用和扩展性的平衡。在人类和机器人的例子中,我们可以看到:
- 固定流程:所有任务都遵循
准备→执行核心任务→清理→报告的统一流程 - 灵活实现:人类和机器人以不同的方式执行核心任务和清理工作
- 代码复用:环境准备和报告生成等通用逻辑在父类中实现,避免重复代码
- 易于扩展:添加新的任务执行者只需实现特定的步骤,而不影响整体算法结构
这种模式特别适用于有固定流程但具体实现可能变化的场景,如各种数据处理流程、工作流引擎、游戏循环等。通过合理使用模板方法,可以提高代码的可维护性和可扩展性。

浙公网安备 33010602011771号