简单工厂模式本质是封装条件分支以集中对象创建逻辑,用函数(如createExporter)替代散落的if-else,返回统一类型实例,需校验type白名单、统一构造参数并导出TS类型。

简单工厂模式的核心不是“设计模式”,而是条件分支的封装
它本质是把 if-else 或 switch 创建对象的逻辑,从调用方抽出来,集中到一个函数或类里。没有接口强制约束,也不涉及继承体系——只要返回的是同一种类型(比如都实现 Product 接口,或都是某个基类实例),就满足基本需求。
别被“工厂”二字带偏:它不解决扩展性问题,只解决“创建逻辑散落各处”的可维护性问题。
用一个静态方法就能实现,不需要额外类
多数场景下,写个带 type 参数的函数就够了,比建 SimpleFactory 类更轻量、更易测试。
-
type值建议用字符串字面量(如"pdf"、"json"),避免魔法数字或枚举带来的耦合 - 返回值类型必须统一,例如都返回
Exporter接口实例,否则调用方无法安全调用.export() - 每个
case分支里直接new具体类,不要再套一层工厂调用,否则变成过度设计
function createExporter(type) {
switch (type) {
case "pdf": return new PdfExporter();
case "json": return new JsonExporter();
case "csv": return new CsvExporter();
default: throw new Error(`Unknown exporter type: ${type}`);
}
}
传入参数时要注意构造函数签名一致性
如果不同产品类的构造函数参数不同(比如 PdfExporter 需要 margin,而 JsonExporter 不需要),简单工厂就很难干净地透传。这时要么:
- 统一构造函数签名,多出的参数设为可选(
options = {}),由具体类自行解析 - 把参数对象整体传入工厂,再按
type拆解后分别传递,但会增加工厂内部逻辑复杂度 - 放弃简单工厂,改用工厂方法或抽象工厂——不过那已经超出“简单”范畴了
常见错误是工厂里硬编码参数顺序,比如 new PdfExporter(config, margin),结果某天 JsonExporter 也需要 config,但位置对不上,立刻报错。
TypeScript 下记得导出类型而非仅值
如果用 TS,光导出工厂函数不够,调用方需要知道返回值类型才能获得自动补全和类型检查。
- 不要只写
function createExporter(type: string): any - 应定义联合类型
type Exporter = PdfExporter | JsonExporter | CsvExporter,并让函数返回Exporter - 或者用类型守卫 + 函数重载,进一步缩小返回类型范围(例如
createExporter("pdf")精确推导为PdfExporter)
没做这步,TS 就退化成 JS,失去大部分静态检查价值。
真正容易被忽略的点在于:简单工厂看似简单,但一旦 type 来源不可控(比如来自 URL 查询参数或用户输入),就必须加白名单校验,否则 eval(`new ${type}()`) 这种漏洞虽不至于出现,但构造非法实例导致后续运行时崩溃的概率很高。










