设计模式中模板方法的钩子使用

1. 模板方法模式(Template Method)说明

模板方法属于行为型设计模式。 核心思想:

  • 在父类(抽象类) 中定义一套固定的算法流程(骨架) ,把步骤拆成多个方法;
  • 骨架方法(模板方法)是 final,不能被子类重写,保证流程顺序不变;
  • 部分步骤是抽象方法,强制子类必须实现;

结构:

  1. 模板方法 templateMethod () :final,按顺序调用各个步骤方法
  2. 抽象方法:必须由子类实现(固定要做的业务)
  3. 钩子方法 hook () :有默认空 / 默认实现,子类可选重写(可选扩展)
csharp 复制代码
// 抽象父类
abstract class AbstractProcess {
    // 模板方法:final,流程固定,禁止重写
    public final void templateMethod() {
        step1();
        step2();
        if (hook()) { // 钩子控制逻辑
            step3();
        }
        step4();
    }

    // 抽象方法:强制子类实现
    protected abstract void step1();
    protected abstract void step2();

    protected void step3() {
        System.out.println("默认step3逻辑");
    }

    // ✅ 钩子函数:默认实现,子类可选覆盖,用来控制流程
    protected boolean hook() {
        return true;
    }

    protected void step4() {
        System.out.println("通用收尾step4");
    }
}

// 子类A
class ProcessA extends AbstractProcess {
    @Override
    protected void step1() {
        System.out.println("A-step1");
    }
    @Override
    protected void step2() {
        System.out.println("A-step2");
    }
    // 不重写hook,使用默认返回true
}

// 子类B,重写钩子改变流程
class ProcessB extends AbstractProcess {
    @Override
    protected void step1() {
        System.out.println("B-step1");
    }
    @Override
    protected void step2() {
        System.out.println("B-step2");
    }
    // 重写钩子,跳过step3
    @Override
    protected boolean hook() {
        return false;
    }
}

调用:

scss 复制代码
new ProcessA().templateMethod();
new ProcessB().templateMethod();

2. 钩子方法

钩子方法两种常见用途:

  1. 作为条件判断:通过返回值,控制程序执行不同的流程
  2. 作为扩展:在流程中间插入自定义逻辑(默认空方法,不执行自定义逻辑)

示例(空钩子):

csharp 复制代码
// 空钩子,子类想加逻辑就重写,不想就不管
protected void beforeFinishHook() {}

在模板中:

scss 复制代码
public final void templateMethod(){
    step1();
    beforeFinishHook();
    step4();
}

3. Spring中的使用

适合:一套流程固定,但其中部分细节 / 可选分支需要不同实现

  • Spring 大量使用:InitializingBean#afterPropertiesSet、Servlet 的 doGet/doPost、GenericApplicationContext 刷新流程里很多钩子
  • 框架:定义主流程,留给业务方在关键点插入自定义逻辑
相关推荐
深入云栈13 分钟前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
JackJiang14 分钟前
IM踩坑:聊天消息ID怎么设计?一个UUID搞不定,我用双ID解决
后端·架构
开心猴爷16 分钟前
iOS 上架 App 流程
后端·ios
code_Bo1 小时前
不只命令行:我把跨 Agent 会话同步做成了桌面应用
前端·javascript·后端
用户8356290780511 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python
用户8356290780512 小时前
Python 如何在 Word 中添加和管理文档变量
后端·python
量化分析码农3 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
程序员cxuan4 小时前
讲真,智能路由这事儿,还得看基元律动
人工智能·后端·程序员
vaskilab4 小时前
Schema 全绿,Agent 却把参数编造了
后端
Java与AI落地4 小时前
Spring AI 上手:给现有 Java 服务加一个能用的 AI 接口
后端