Skip to content

模板方法模式(Template Method Pattern)笔记

定义

模板方法模式是一种行为设计模式,它在父类中定义了一个算法的框架,允许子类在不改变算法结构的情况下重写算法的特定步骤。

英文原文定义

The Template Method Pattern defines the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.

核心概念

模板方法模式通过将不变的行为移到父类,去除子类中的重复代码,同时保留特定步骤的灵活性。这是通过"好莱坞原则"("Don't call us, we'll call you")实现的,即父类控制流程,子类提供具体实现。

主要角色

  1. AbstractClass(抽象类):定义算法骨架和基本操作(包括模板方法和基本方法)
  2. ConcreteClass(具体子类):实现父类定义的抽象操作,完成算法中与特定子类相关的步骤

优缺点

优点

  • 代码复用:将公共行为提取到父类,避免代码重复
  • 反向控制:通过"好莱坞原则"实现反向控制结构
  • 扩展性好:符合开闭原则,增加新的子类即可扩展行为
  • 封装不变部分:将不变的行为封装在父类,可变部分由子类实现

缺点

  • 限制灵活性:算法框架固定,可能限制子类的灵活性
  • 增加系统复杂度:每个不同实现都需要一个子类,可能导致类数量增加
  • 违反里氏替换原则:如果子类对模板方法进行重写而非仅实现抽象步骤,可能违反LSP

解决的问题

模板方法模式主要解决以下经典问题:

  1. 算法框架固定但部分步骤可变:当多个类包含几乎相同的算法,只有某些小部分不同时
  2. 消除重复代码:当多个子类有共同行为时,可以避免代码重复
  3. 控制子类扩展点:当需要严格控制子类的扩展方式时
  4. 框架设计:在框架设计中特别有用,框架定义流程,用户实现具体步骤

实现注意事项

  1. 模板方法声明为final:通常应将模板方法声明为final,防止子类重写整个算法
  2. 基本方法设计
    • 抽象方法:必须由子类实现
    • 钩子方法:可选实现,提供默认空实现
    • 具体方法:固定实现,子类通常不应修改
  3. 命名约定:对需要子类实现的方法使用"do"前缀(如doGenerateReport)
  4. 访问控制:基本方法应尽可能protected,避免public暴露过多细节
  5. 避免过度抽象:只有当确实存在多个变体时才使用此模式

实现变体

  1. 纯抽象方法变体:所有步骤都是抽象的,必须由子类实现
  2. 钩子方法变体:提供可选步骤(钩子方法),子类可选择实现
  3. 默认实现变体:提供一些步骤的默认实现,子类可选择覆盖

与其他模式的关系

相似模式区分

  1. 策略模式

    • 模板方法:使用类继承,编译时确定算法结构
    • 策略模式:使用对象组合,运行时改变行为
  2. 工厂方法模式

    • 工厂方法模式常作为模板方法模式的一个特例
    • 工厂方法通常只定义一个步骤的创建逻辑
  3. 装饰器模式

    • 模板方法:通过子类化扩展行为
    • 装饰器:通过对象组合动态添加职责

常见搭配组合

  1. 模板方法 + 工厂方法:模板方法中的某些步骤使用工厂方法创建对象
  2. 模板方法 + 策略模式:模板方法中可变的步骤使用策略对象
  3. 模板方法 + 钩子方法:提供更多扩展点控制流程

典型应用场景

  • 框架设计(如Spring的JdbcTemplate)
  • 文档生成(固定流程,不同格式)
  • 数据处理管道(固定处理流程,可变处理逻辑)
  • 游戏循环(固定游戏循环,可变渲染/更新逻辑)
  • 测试框架(固定测试流程,可变测试用例)

代码示例(伪代码)

java
// 抽象类
abstract class DataProcessor {
    // 模板方法(final防止重写)
    public final void processData() {
        openConnection();
        readData();
        transformData();
        if (needLog()) {
            writeLog();
        }
        closeConnection();
    }
    
    // 基本方法
    protected abstract void readData();
    protected abstract void transformData();
    
    protected void openConnection() {
        // 默认实现
    }
    
    protected void closeConnection() {
        // 默认实现
    }
    
    // 钩子方法
    protected boolean needLog() {
        return false;
    }
    
    private void writeLog() {
        // 固定实现
    }
}

// 具体子类
class CSVProcessor extends DataProcessor {
    protected void readData() {
        // 读取CSV实现
    }
    
    protected void transformData() {
        // CSV转换实现
    }
    
    protected boolean needLog() {
        return true; // 覆盖钩子方法
    }
}