这种情况在创建复杂的对象插入数据库时尤为常见。我可能有一个需要 20 个字段的对象,每个字段都来自其他地方。
interface Cat {hair: HairType, name: string, ...20 other properties}
function insertCatIntoDB(cat: Cat){...}
function createCatForUser(userType: UserType){
const newCat: Partial<Cat> = {};
newCat.name = getNewCatNameForUserType(userType);
...business logic involving the setting of the other properties
insertCatIntoDB(newCat); // Problem: newCat is Partial<Cat>
// instead of Cat despite having assigned all of the properties
}
我看到了几种解决方法。
insertCatIntoDB({hair: getHairByUserType, name: getNameByUserType, ...})
但是,如果创建属性所需的业务逻辑相对简单,那么您将创建 20 个函数,每个函数可能有 3 行代码,这些函数只会被调用一次,这对于可读性来说不是很好。
insertCatIntoDB({name: userType === UserType.girl ? 'cookie' : (userType === userType.boy ? 'tiger' : 'persian'), ...})
但即使在这个具有非常简单逻辑的示例中,这也会很快变得笨拙且难以阅读。
insertCatIntoDB(newCat as Cat)
但这不是类型检查。
我正在寻找有关处理这些情况的更好方法的建议。
答案 0 :(得分:1)
当我查看您界面中的属性数量并根据您的重构想法时,我对此有几个想法:
根据Interface segregation principles
将此接口拆分为更小的接口。我们可以使用 Information experts principle
和 High cohesion principle
来创建几个接口,这些接口包含几个高内聚属性的信息。这样,不用创建20个函数来按类型获取属性,只需要几个实例即可。
使用工厂模式创建 getNameByUserType、getHairByUserType、getOtherAttributesByType 等...
使用Builder模式初始化cat对象,将上述工厂注入到builder中(参考:https://refactoring.guru/design-patterns/builder)。例如:
const cat = new CatBuilder()
.byUserType(userType)
.withGetByUserTypeFactory(GetByUserTypeFactory)
.withHair()
.withName()
.(...other attributes...)
.build();