0128_模板方法(Template Method)

模板方法(Template Method)

意图

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

UML 图

TemplateMethod

优点

  1. 代码复用:将公共行为移到父类中,避免代码重复
  2. 封装不变部分:固定算法结构,保护核心算法不被修改
  3. 扩展性好:通过子类扩展具体实现,符合开闭原则
  4. 便于维护:算法修改只需在父类中进行,子类不受影响
  5. 提高灵活性:子类可以灵活实现特定步骤,而不影响整体结构

缺点

  1. 限制扩展性:算法框架固定,可能限制子类的灵活性
  2. 增加系统复杂度:每个不同实现都需要一个子类,可能导致类数量增加
  3. 违反里氏替换原则:如果子类对模板方法进行重写,可能破坏父类定义的行为
  4. 调试困难:模板方法中的步骤调用可能在多个子类中实现,调试较复杂
  5. 可能产生过多抽象:如果步骤划分过细,可能导致系统过于抽象

代码示例

以人类和机器人执行任务的不同方式为例:

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标准库中的广泛应用:

  1. 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;
}
  1. 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);
}
  1. 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) {
        // 默认实现
    }
}
  1. 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);
}

总结

模板方法模式通过定义算法的骨架而将一些步骤延迟到子类中,实现了代码复用和扩展性的平衡。在人类和机器人的例子中,我们可以看到:

  • 固定流程:所有任务都遵循准备→执行核心任务→清理→报告的统一流程
  • 灵活实现:人类和机器人以不同的方式执行核心任务和清理工作
  • 代码复用:环境准备和报告生成等通用逻辑在父类中实现,避免重复代码
  • 易于扩展:添加新的任务执行者只需实现特定的步骤,而不影响整体算法结构

这种模式特别适用于有固定流程但具体实现可能变化的场景,如各种数据处理流程、工作流引擎、游戏循环等。通过合理使用模板方法,可以提高代码的可维护性和可扩展性。

posted @ 2025-09-15 20:36  庞去广  阅读(6)  评论(0)    收藏  举报