← 返回题目列表

模板方法模式和工厂方法模式有什么关系?

高频 中等 第 5 / 26 题 更新于 2026/07/28
模板方法模式工厂方法模式设计模式对比扩展点

简化版

模板方法模式关注固定算法流程,工厂方法模式关注把对象创建延迟到子类。两者都可能使用继承和抽象方法,但意图不同:模板方法让子类填流程步骤,工厂方法让子类决定创建哪种对象。

详细版

模板方法模式和工厂方法模式容易被放在一起问,因为它们都常见于框架设计,也都可能出现父类调用子类方法。

模板方法模式:

  • 父类定义业务流程;
  • 子类实现某些流程步骤;
  • 关注行为流程复用。

工厂方法模式:

  • 父类定义创建对象的抽象方法;
  • 子类决定具体创建哪种产品;
  • 关注对象创建解耦。

它们也可以组合:模板方法的某个步骤可能是工厂方法。例如父类固定处理流程,但某一步需要创建不同处理器,就把创建动作交给子类工厂方法。

完整版教学

一、两者共同点是都可能依赖继承

模板方法模式和工厂方法模式都可能长成这样:

抽象父类
  -> 抽象方法
  -> 子类实现抽象方法

但设计模式不能只看类图。它们的区别在意图。

模板方法解决“流程如何复用”,工厂方法解决“对象如何创建”。

二、模板方法关注流程

模板方法模式中的抽象方法通常表示流程中的一个步骤。

public final void execute() {
    prepare();
    doExecute();
    finish();
}

protected abstract void doExecute();

这里 doExecute() 是业务步骤。父类关心的是整个执行流程。

三、工厂方法关注创建

工厂方法模式中的抽象方法通常负责创建产品对象。

public abstract class Dialog {
    public void render() {
        Button button = createButton();
        button.render();
    }

    protected abstract Button createButton();
}

这里 createButton() 的重点是创建对象,而不是完成业务流程中的某个算法步骤。

子类决定创建 WindowsButton 还是 WebButton。

四、两者可以自然组合

很多框架里会同时出现两种模式。

例如父类模板方法固定流程:

创建处理器 -> 初始化 -> 执行 -> 销毁

其中“创建处理器”这一步可以交给子类:

protected abstract Handler createHandler();

这个抽象方法既是模板流程中的一步,也承担工厂方法的创建职责。

所以它们不是互斥关系,而是关注点不同。

五、面试回答要抓“意图”

如果面试官问两者区别,不要只回答“一个行为型,一个创建型”。这只是分类。

更好的回答是:

  • 模板方法模式把固定流程放父类,让子类实现变化步骤;
  • 工厂方法模式把对象创建放到子类,避免父类依赖具体产品;
  • 两者都可以通过抽象方法扩展,但一个扩展行为步骤,一个扩展创建对象。

六、流程扩展点与对象创建扩展点

文档处理模板有 4 个步骤,其中 createParser() 返回 PDF 或 CSV 解析器;前者是模板骨架,后者是其中 1 个工厂方法。

template.process -> createParser(factory method) -> parse -> validate -> save

这里真正需要保护的是父类掌握的流程不变量:客户端只能进入模板入口,子类只能改写约定好的步骤。评审时应逐步标出哪些行为固定、哪些行为必须实现、哪些行为只是可选钩子,避免父类和子类互相猜测。

七、继承边界与流程契约验证

检查维度应确认的内容
机制正确性看到父类和子类不能直接下结论,必须找到扩展点到底是行为步骤还是对象创建。
适用边界模板方法解决“步骤顺序怎样固定”,工厂方法解决“具体产品由谁创建”;它们经常组合而非互斥。
测试证据对两种实现运行同一父类契约测试,验证固定步骤顺序一致,再分别验证各自变化步骤
工程代价重点评估父类改动会影响多少子类、protected 扩展面有多大,以及新增变化是否迫使无关子类一起修改

易错点:看到父类和子类不能直接下结论,必须找到扩展点到底是行为步骤还是对象创建。

八、常见误区与追问

  • 误区:两者都用继承,所以本质相同。 代码结构相似不等于意图相同,一个组织算法流程,一个延迟产品创建。
  • 误区:模板方法要求所有步骤都由子类覆写。 稳定步骤应在父类直接实现;只有必要变化点才做抽象步骤,可选变化点才做有默认实现的钩子。
  • 追问:工厂方法必须出现在模板方法里吗? 不必须;它可以独立被客户端或其他流程调用,组合只是常见用法。
  • 追问:模板方法为什么常声明为 final? 为了防止子类改写算法骨架和步骤顺序;若框架有意允许重写,则必须明确不变量和扩展契约。
  • 追问:模板方法最关键的回归测试是什么? 是父类契约测试:所有子类都必须满足固定步骤顺序、公共前后置行为和异常清理规则。

九、加强记忆

模板方法和工厂方法都可能用继承,但目的不同。模板方法问的是“流程怎么走”,工厂方法问的是“对象谁来造”;它们可以组合,工厂方法也可以成为模板流程中的一个步骤。