飞翔飞翔
主页
  • 计算机基础

    • TCP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 前言

    • 1.设计模式导图
  • 第1章 创建型模式

    • 1.单例模式
    • 2.工厂方法模式
    • 3.抽象工厂模式
    • 4.建造者模式
    • 5.原型模式
  • 第2章 结构型模式

    • 1.适配器模式
    • 2.桥接模式
    • 3.组合模式
    • 4.装饰器模式
    • 5.外观模式
    • 6.享元模式
    • 7.代理模式
  • 第3章 行为型模式

    • 1.模板方法模式
    • 2.策略模式
    • 3.命令模式
    • 4.责任链模式
    • 5.中介者模式
    • 6.备忘录模式
    • 7.观察者模式
    • 8.状态模式
    • 9.访问者模式
    • 10.解释器模式
    • 11.迭代器模式

模板方法模式

概念

模板方法模式(Template Method Pattern)是一种行为型设计模式,其核心思想是定义一个算法的骨架,允许子类在不改变算法结构的情况下重定义某些步骤。父类通过模板方法控制流程,子类通过实现抽象方法填充细节,实现反向控制结构(父类调用子类)。

作用

  1. 代码复用:将公共逻辑抽取到父类,避免重复代码。

  2. 扩展性:子类只需关注差异部分,符合开闭原则。

  3. 流程控制:父类固定核心流程,防止子类破坏执行顺序。

场景

  1. 多个类具有相似流程但部分步骤不同( 如数据解析、文件处理 )。

  2. 需要固定核心算法流程,允许子类扩展特定步骤。

  3. 框架设计(如 Spring 的 JdbcTemplate )。

举例

// 饮料类
abstract class Beverage {
    // 准备食谱:模板方法 (final防止子类覆盖)
    public final void prepareRecipe() {
        // 烧开水
        boilWater();
        // 泡
        brew();
        // 倒入杯子
        pourInCup();
        // 是否加入调味剂
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    // 固定步骤:烧开水
    private void boilWater() {
        System.out.println("烧开水");
    }
    // 固定步骤:倒入杯子
    private void pourInCup() {
        System.out.println("倒入杯子");
    }

    // 抽象方法(必须实现)
    abstract void brew();
    abstract void addCondiments();

    // 钩子方法(可选覆盖)
    boolean customerWantsCondiments() {
        return true;
    }
}
class Coffee extends Beverage {
    @Override
    void brew() {
        System.out.println("冲泡咖啡粉");
    }

    @Override
    void addCondiments() {
        System.out.println("加糖和牛奶");
    }

    @Override
    boolean customerWantsCondiments() {
        return false; // 示例:咖啡不要调料
    }
}
class Tea extends Beverage {
    @Override
    void brew() {
        System.out.println("浸泡茶叶");
    }

    @Override
    void addCondiments() {
        System.out.println("加柠檬");
    }
}

运行示例:

public class BeverageDemo {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        coffee.prepareRecipe();

        System.out.println("---");

        Beverage tea = new Tea();
        tea.prepareRecipe();
    }
}

控制台输出:

烧开水
冲泡咖啡粉
倒入杯子
---
烧开水
浸泡茶叶
倒入杯子
加柠檬

反例

class CoffeeWithoutPattern {
    public void makeCoffee() {
        System.out.println("烧开水");
        System.out.println("冲泡咖啡粉");
        System.out.println("倒入杯子");
        System.out.println("加糖和牛奶"); // 重复代码
    }
}
class TeaWithoutPattern {
    public void makeTea() {
        System.out.println("烧开水");       // 重复代码
        System.out.println("浸泡茶叶");
        System.out.println("倒入杯子");    // 重复代码
        System.out.println("加柠檬");
    }
}

不使用模板方法模式时,存在以下问题:

  1. 重复代码:烧开水、倒入杯子等公共步骤在多个类中重复实现。

  2. 维护困难:修改流程需改动所有相关类,成本高。

  3. 流程失控:子类可能遗漏步骤或改变执行顺序,破坏业务逻辑。

原理

模板方法模式通过父类定义算法骨架( 模板方法 ),将可变步骤抽象为方法( 抽象方法或钩子方法 ),子类通过实现这些方法填充细节。模板方法使用 final 修饰防止子类覆盖,确保核心流程统一;钩子方法提供默认实现,子类可选择性覆盖以调整行为。

缺点

  1. 增加类数量:每个差异步骤需对应一个子类,可能导致类爆炸。

  2. 父类耦合:父类修改可能影响所有子类,需谨慎设计抽象方法。

  3. 继承复杂度:过度使用可能导致继承层次过深,系统难以理解。


总结


模板方法模式通过父类控制流程、子类填充细节的方式,有效解决多类相似流程的代码复用问题,尤其适合需要严格流程控制的场景(如框架设计)。其核心价值在于统一算法结构、降低维护成本,但需注意避免过度继承导致的系统复杂度上升。
下一页
2.策略模式