java - 根据类型层次结构创建映射函数
问题描述
我有一个遵循领域驱动设计规则的应用程序。DDD的规则之一是领域层不应该依赖于基础设施层。我有一个工具可以检查从域到基础设施是否存在任何依赖项(导入)。在我的基础设施层,我有一个这样的类层次结构:
在我的域层中,如下所示:
现在,我需要将我的域类映射到基础设施实体,以便将它们保存在我的数据库中。
我的域中有一个输出端口,它是一个接口:
// infra/ports/out/RuleRepository.java
public interface RuleRepository {
Rule save(Rule rule);
}
此接口在基础设施层中实现:
// domain/RuleRepositoryJpaAdapter.java
public class RuleRepositoryJpaAdapter implements RuleRepository {
// extends CrudRepository<RuleEntity, Long>
RuleCrudRepository jpaRepository;
RuleMapper mapper;
@Override
public Rule save(Rule rule) {
return jpaRepository.save(mapper.mapToEntity(rule))
.mapToDomain();
}
}
我正在寻找一种mapToEntity
无需检查规则类型即可实现的方法。最好的方法是向 , 添加一个方法,mapToEntity
但这Rule
会破坏检查域和基础设施层之间是否存在任何导入的单元测试。如果有其他方法吗?IpRule
BlackListRule
我现在拥有的:
public class RuleMapper {
public RuleEntity mapToEntity(Rule rule) {
if (rule instanceof IpRule) {
return new IpRuleEntity().mapFromDomain(rule);
} else if (rule instanceof BlackListRule) {
return new BlackListRuleEntity().mapFromDomain(rule);
} else {
throw new IllegalArgumentException("Unexpected argument of type " + (rule == null ? "null" : rule.getClass().getName()));
}
}
}
解决方案
在此示例中,它可能如下所示:
public abstract class Rule {
// Maps a rule to a result type T
public interface Mapper<T> {
T mapIpRule(IpRule rule);
T mapBlackListRule(BlackListRule rule);
}
public abstract <T> T map(Mapper<T> mapper);
// ...
}
public class IpRule extends Rule {
@Override
public <T> T map(Mapper<T> mapper) {
return mapper.mapIpRule(this);
}
// ...
}
public class BlackListRule extends Rule {
@Override
public <T> T map(Mapper<T> mapper) {
return mapper.mapBlackListRule(this);
}
// ...
}
public class RuleMapper implements Rule.Mapper<RuleEntity> {
public RuleEntity mapToEntity(Rule rule) {
return rule.map(this);
}
@Override
public RuleEntity mapIpRule(IpRule rule) {
return new IpRuleEntity();
}
@Override
public RuleEntity mapBlackListRule(BlackListRule rule) {
return new BlackListRuleEntity();
}
}
它有一个很好的特性,即在编译时检查所有子类型都被正确处理。如果稍后添加新的子类型Rule
,则需要实现该map
方法,这将需要向Rule.Mapper
接口添加一个方法,这反过来又需要RuleMapper
实现来实现该方法。在使用运行时类型检查的问题中给出的示例中,instanceof
可能会错过一个案例,导致IllegalArgumentException
运行时出现。
但是,您需要判断额外的复杂性对于您的具体情况是否值得。可能是你现有RuleMapper
的很好。