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

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 刷新流程里很多钩子
  • 框架:定义主流程,留给业务方在关键点插入自定义逻辑
相关推荐
我的div丢了肿么办1 小时前
go语言对路由中的业务逻辑进行抽离
后端·go
leo在掘金1 小时前
纯Rust重写Photoshop,一个月7.2万Star
后端·架构
韩振方1 小时前
Kubernetes 通过资源 requests 决定 Pending Pod 能否找到节点
后端
用户360055579001 小时前
Kestrel_VLLM - 18 · 投机解码位级对拍收口:batch 与 M=1 一致,注意力路径与 CPU 逐字节对齐
后端
Thneonl1 小时前
git reset --hard 之后先别哭:reflog 里存着你刚弄丢的那个分支
运维·后端
弦儿1 小时前
后端 Web 实战:员工管理模块(多表关系 + 多表查询 + 分页查询 + 条件分页)
后端·sql
王中阳Go1 小时前
网页上答对、接口里答错:同一个知识库,差的不是模型是入口
人工智能·后端·架构
郝琳1 小时前
真实 flaky 18.3%,CI 报 0%,让 Agent 修测试,它删掉了被测的变量
后端·ai编程
子兮曰1 小时前
Bun v1.4.4 实测:2,025 个文件,bun fmt 2.6 秒跑完
前端·后端·bun