前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库工厂模式 何时使用 对象创建
设计设计模式可维护代码

什么信号表明一段对象创建逻辑应该收敛为工厂而不是散落在各处 new?

重复的new若依赖装配或条件分支,且创建逻辑可能变化时,可考虑用工厂。把易变的创建决策集中管理,才能避免遗漏修改。

前端进阶之旅 · 一题精讲更新于 2026.09.05
设计模式#可维护代码
先看核心答案
理解线索

散落new的坏味道

  1. 重复构造代码多调用点粘贴相似的new逻辑
  2. 条件分支选择需要按类型配置选不同子类
  3. 依赖装配复杂创建对象前须解析外部配置

只有同时出现重复和变化才值得为工厂付出间接层,单个简单new不应当被包装。

核心回答

先记住这个答案

若对象创建需要组合配置、查分支或注入依赖,而这些步骤散落在多个调用点,那么新增类型或更改参数往往要改所有new语句。工厂将这一过程封装进单一入口,让调用方只表达意图,创建细节与类型选择都在内部处理。不过,只有当下述信号同时满足时才值得引入:重复的new代码、条件依赖或装配复杂度高,且这些逻辑预计会变化。

  • 重复的new代码是工厂信号
  • 依赖装配或分支时优先考虑工厂
  • 不要为简单创建过度引入工厂

散落`new`的复制粘贴成本

当对象构造需要传多个参数,有些来自环境变量,有些来自上一个模块计算,每个调用点都重复写new Foo(...)时,这些参数的顺序和含义必须同步维护。一旦某天新增依赖或调整构造签名,改动必须遍历所有调用点,而遗漏不会立刻报错,要到支付或请求时才暴露。

更隐蔽的是类型分支:不同业务页面都各自用if (type === 'wechat')创建对应处理器。条件判断本身、参数来源和异常兜底被复制到各处,以后添加'银联'时,只要某处忘记改,该入口就使用缺失对象直接崩掉。此时创建逻辑应该内聚为单一入口。

一个支付处理器的工厂重构过程

假设订单系统原先在收款、退款、对账三处分别写new WechatPay({ appid, secret })和new AlipayPay({ pid, key })。每次加新渠道,都要在三个业务流程里找到对应位置,更新条件与参数。某次只改了两处,第三处遗漏后,对账入口抛出了TypeError。

重构后定义PaymentFactory.create(type, context),内部持有渠道映射与配置。调用方统一传渠道名和上下文,工厂负责从配置读取密钥并返回实例。新增强银联时,只需在工厂注册union,业务代码完全不变,也避免了三处条件不一致。

工厂不是为所有`new`准备的

如果对象只是new Car(500),构造参数单且不会变,且全系统只有一处调用,那么引入工厂就是多余的间接层。因为它要求读者先查看工厂返回什么,再跳回构造函数,阻断了直接理解。

另一种情况是创建方式虽重复,但结构简单且稳定——比如三处都创建同一个内部工具类。只要它未来不会增加类型或参数,复制几次也比单工厂更加清晰。只有当创建逻辑自身具有变化轴时,工厂才有隔离价值。

回答前,多想一步

容易答错的地方

只要`new`出现多就应改工厂
判断信号不是出现次数,而是创建逻辑是否可能独立演化。如果两处new完全相同且稳定,工厂不会带来收益,反而增加一层抽象。工厂要解决的是因重复引起的高修改成本。
工厂一定比直接`new`更适合JavaScript
工厂函数能隐藏原型和this细节,但取决于实现,它可能让调用方无法直接通过instanceof判断具体类型(除非工厂内部显式构造对象),因此类型识别通常更间接。当对象结构简单,用构造器时创建意图更清晰,所以不应当用单一标准套用所有代码。
试着用自己的话回答

面试官还会怎么问?

如何用代码扫描迅速排查散落的`new`?

搜索同一构造函数的出现点,逐处检查周围是否有相同类型判断和参数拼装。如果出现频次高且每次代码相似,就应考虑收敛为工厂,否则可以先记录为可疑点。

工厂模式和构造器在异常处理上有什么区别?

构造器只能通过throw告知失败,调用方需自己捕获;工厂可捕获内部创建异常并转为统一的业务错误类型,还能对部分参数做默认兜底,但它必须面向应用场景提供策略。

工厂内部巨大switch如何继续拆分?

把switch换成注册表映射和创建函数数组,让工厂只做分发查找。新类型注册到结构体里,而不是每次打开文件扩展case。

从一道题,走向一组知识

把知识连起来

可维护代码

简单工厂、工厂方法与抽象工厂三种工厂模式分别解决什么创建问题?

同属「可维护代码」专题,接着看 工厂模式 简单工厂 工厂方法 抽象工厂 区别 在具体场景中的处理方式。

可维护代码

观察者模式与发布订阅模式在耦合方式上的核心区别是什么?

同属「可维护代码」专题,接着看 观察者模式 发布订阅 区别 在具体场景中的处理方式。

参考资料

  • Working with objects

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 散落`new`的复制粘贴成本
  3. 一个支付处理器的工厂重构过程
  4. 工厂不是为所有`new`准备的
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑