工厂函数必须返回统一接口类型(如BusinessModel),通过字段映射适配不同输入,避免副作用,且方法实现需遵守接口契约。

工厂函数必须返回一致的接口类型,否则类型检查会失败
TypeScript 下如果 createUserModel 返回 User,而 createOrderModel 返回 Order,调用方就无法用统一变量接收。必须让所有工厂函数返回同一个接口,比如 BusinessModel:
interface BusinessModel {
id: string;
createdAt: Date;
validate(): boolean;
}
<p>function createUserModel(data: any): BusinessModel {
return {
id: data.id,
createdAt: new Date(data.createdAt),
validate() { return !!this.id; }
};
}</p><p>function createOrderModel(data: any): BusinessModel {
return {
id: data.orderId,
createdAt: new Date(data.placedAt),
validate() { return this.id.length > 8; }
};
}注意:字段名不强制对齐(id vs orderId),但接口契约必须收敛到 BusinessModel。
批量创建时别直接 new 实例,用工厂函数数组 + map
常见错误是写一堆 new UserModel()、new OrderModel(),导致新增模型就得改创建逻辑。正确做法是把工厂函数存进数组,再统一调用:
const factories = [createUserModel, createOrderModel, createProductModel];
<p>const rawData = [
{ id: 'U100', createdAt: '2024-01-01' },
{ orderId: 'ORD-7890', placedAt: '2024-01-02' },
{ productId: 'P555', listedAt: '2024-01-03' }
];</p><p>const models = rawData.map((https://www.php.cn/link/0b845236da4ce3d6e20524161c1966c0, i) => factories<a href="https://www.php.cn/link/0b845236da4ce3d6e20524161c1966c0">i</a>);这样新增模型只需往 factories 数组末尾加一个函数,并确保 rawData 顺序匹配——若顺序不可控,就该用带 type 字段的联合数据结构。
传入数据结构不一致时,工厂内部做字段映射,别甩给调用方
业务数据源五花八门:API 响应字段名不同、数据库列名缩写、CSV 头部大小写混用。工厂函数要承担适配责任,而不是要求上游“统一字段”:
-
createUserModel应能处理{ user_id: 'U1', created_at: '...' }和{ id: 'U1', createdAt: '...' }两种输入 - 建议在工厂内部用解构默认值或
Object.assign归一化字段:const { id = data.user_id || data.userId, createdAt = data.created_at || data.createdAt } = data; - 避免在工厂外写重复的字段转换逻辑,那会破坏“统一接口”的封装性
不要在工厂里做重 IO 或复杂计算,它只负责构造
工厂模式的核心职责是“创建对象”,不是“加载数据”或“校验权限”。以下行为会污染工厂语义:
- 在
createOrderModel里发起 HTTP 请求查用户信息 - 调用
validate()时触发数据库唯一性检查 - 构造时解析大文件或渲染模板
这些逻辑应拆到 service 层或 model 的方法中。工厂函数应保持纯(pure)或至少无副作用——否则批量创建时性能陡降,且难以单元测试。
真正容易被忽略的是:工厂返回的对象,其方法(如 validate)是否也遵循了接口契约?如果某个模型的 validate 抛异常而其他模型只返回布尔值,那统一调用就会出问题。

















