将对象集合映射为另一对象集合的最优实现方案
最优实现方案:类型映射注册表
新手方案用instanceof遍历判断的问题很明显:每次新增Model类型都要修改遍历逻辑里的条件分支,违反开闭原则,代码会随着类型增多变得臃肿且耦合度高。最优方案是用类型映射注册表,把类型与对应的映射逻辑解耦。
实现步骤
- 定义映射注册表:用一个
Map(或普通对象)存储「Model类型」到「映射函数/目标类构造器」的对应关系 - 注册映射规则:提前把每个Model类型对应的映射逻辑注册到表中
- 通用映射函数:遍历集合时,直接通过Model的类型从注册表中获取对应的映射逻辑,执行映射
代码示例(TypeScript)
假设我们有统一接口BaseModel,以及两个实现类UserModel、OrderModel,要映射为UserDto、OrderDto:
// 定义基础接口 interface BaseModel { id: string; } // 具体Model类 class UserModel implements BaseModel { id: string; username: string; constructor(id: string, username: string) { this.id = id; this.username = username; } } class OrderModel implements BaseModel { id: string; totalAmount: number; constructor(id: string, totalAmount: number) { this.id = id; this.totalAmount = totalAmount; } } // 目标DTO类 class UserDto { userId: string; userName: string; constructor(model: UserModel) { this.userId = model.id; this.userName = model.username; } } class OrderDto { orderId: string; amount: number; constructor(model: OrderModel) { this.orderId = model.id; this.amount = model.totalAmount; } } // 1. 创建类型映射注册表 const modelToDtoMap = new Map<typeof BaseModel, (model: BaseModel) => any>([ [UserModel, (model) => new UserDto(model as UserModel)], [OrderModel, (model) => new OrderDto(model as OrderModel)] ]); // 2. 通用映射函数 function mapModelsToDtos(models: BaseModel[]) { return models.map(model => { const mapper = modelToDtoMap.get(model.constructor as typeof BaseModel); if (!mapper) { throw new Error(`未找到${model.constructor.name}对应的映射规则`); // 或者返回默认处理结果:return { id: model.id }; } return mapper(model); }); } // 使用示例 const models: BaseModel[] = [ new UserModel("u1", "张三"), new OrderModel("o1", 99.9) ]; const dtos = mapModelsToDtos(models); console.log(dtos);
优势
- 符合开闭原则:新增Model类型时,只需要添加对应的映射规则到注册表,无需修改遍历/判断逻辑
- 低耦合:类型与映射逻辑分离,代码更易维护和扩展
- 可读性强:所有映射关系集中在注册表中,一目了然
注意事项
- 如果是JavaScript环境,要确保
model.constructor能正确获取到类型(避免类被混淆压缩导致的问题,可考虑用自定义标识比如model.type代替构造函数作为键) - 可添加默认映射逻辑,避免未注册类型导致的报错
内容的提问来源于stack exchange,提问作者olechafm
相关产品推荐
相关产品推荐

