工厂模式在JavaScript中用于解耦对象创建逻辑,支持函数工厂(返回纯对象)、类工厂(返回实例并共享方法)和配置驱动工厂(通过schema扩展),适用于动态生成不同结构数据对象的场景。

工厂模式在 JavaScript 中主要用于解耦对象的创建逻辑,避免直接使用 new 调用构造函数,让创建过程更灵活、可配置。它特别适合需要根据条件动态生成不同结构或行为的数据对象的场景。
用函数工厂封装创建逻辑
最轻量的方式是定义一个返回对象的普通函数,内部根据参数决定返回哪种数据结构:
- 函数接收类型标识(如字符串
"user"、"product")和初始化数据 - 内部用
switch或对象映射决定字段、默认值、计算属性等 - 返回纯对象(不依赖原型),适合配置化、临时性数据对象
示例:
function createDataObject(type, data = {}) {
switch (type) {
case 'user':
return {
id: data.id || Date.now(),
name: data.name || 'Anonymous',
createdAt: new Date().toISOString(),
role: data.role || 'user'
};
case 'product':
return {
sku: data.sku || `P${Date.now()}`,
title: data.title || 'Untitled',
price: Number(data.price) || 0,
inStock: data.inStock !== undefined ? Boolean(data.inStock) : true
};
default:
throw new Error(`Unknown type: ${type}`);
}
}
const user = createDataObject('user', { name: 'Alice' });
const product = createDataObject('product', { title: 'Laptop', price: 999 });
用类工厂支持实例化与原型方法
当需要共享方法、继承或保持 instanceof 可识别性时,可结合类与工厂函数:
立即学习“Java免费学习笔记(深入)”;
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 定义多个专用类(
User、Product)并暴露其构造器 - 工厂函数根据类型返回对应类的新实例
- 实例拥有原型方法,便于复用逻辑(如
user.getDisplayName())
示例:
class User {
constructor({ id, name, role = 'user' }) {
this.id = id || Date.now();
this.name = name || 'Anonymous';
this.role = role;
}
getDisplayName() {
return `${this.name} (${this.role})`;
}
}
class Product {
constructor({ sku, title, price = 0 }) {
this.sku = sku || `P${Date.now()}`;
this.title = title || 'Untitled';
this.price = Number(price);
}
isExpensive() {
return this.price > 500;
}
}
function createInstance(type, data) {
const factories = {
user: () => new User(data),
product: () => new Product(data)
};
const factory = factories[type.toLowerCase()];
if (!factory) throw new Error(`No factory for type: ${type}`);
return factory();
}
const u = createInstance('user', { name: 'Bob', role: 'admin' });
console.log(u.getDisplayName()); // "Bob (admin)"
用配置驱动工厂提升扩展性
把类型定义、字段规则、校验逻辑抽成配置,让工厂更易维护和扩展:
- 定义一个配置表,每个类型包含
schema(字段名+默认值/类型)、init(初始化钩子)等 - 工厂统一处理数据合并、类型转换、必填校验
- 新增类型只需加配置,无需改工厂主逻辑
示例片段:
const SCHEMA_CONFIG = {
user: {
schema: { id: Date.now, name: '', email: '', isActive: true },
validate: ({ email }) => /^\S+@\S+\.\S+$/.test(email)
},
order: {
schema: { orderId: () => `ORD-${Date.now()}`, items: [], total: 0 },
transform: (raw) => ({ ...raw, placedAt: new Date().toISOString() })
}
};
function createFromSchema(type, input = {}) {
const config = SCHEMA_CONFIG[type];
if (!config) throw new Error(`No schema for ${type}`);
const data = {};
for (const [key, def] of Object.entries(config.schema)) {
data[key] = typeof def === 'function' ? def() : def;
}
Object.assign(data, input);
if (config.transform) Object.assign(data, config.transform(data));
if (config.validate && !config.validate(data)) {
throw new Error(`${type} validation failed`);
}
return data;
}
注意事项与适用边界
工厂模式不是银弹,需注意几点:
- 简单对象(如仅含字段)优先用字面量或
Object.assign(),避免过度设计 - 若所有对象共用大量逻辑,考虑组合模式或策略模式配合工厂
- ES6 模块中可将工厂函数默认导出,类型类按需导入,减少打包体积
- 配合 TypeScript 使用时,为工厂函数添加泛型重载,能获得精准类型推导

















