Chr*_*311 5 java polymorphism abstract-class code-duplication
我想摆脱下面的代码重复MyFacadeBean.考虑以下情况:
public class FacadeBean implements Facade {
@EJB
private CrudService crudService;
@Inject
private FirstAssembler firstAssembler;
@Inject
private SecondAssembler secondAssembler;
@Inject
private ThirdAssembler thridAssembler;
@Inject
private FourthAssembler fourthAssembler;
@Override
public void save(FirstValue value) {
FirstEntity entity = this.firstAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
@Override
public void save(SecondValue value) {
SecondEntity entity = this.secondAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
@Override
public void save(ThirdValue value) {
ThirdEntity entity = this.thirdAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
@Override
public void save(FourthValue value) {
FourthEntity entity = this.fourthAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
}
public interface MyFacade {
void save(FirstValue value);
void save(SecondValue value);
}
Run Code Online (Sandbox Code Playgroud)
随着CrudService:
public interface CrudService {
void persist(Object entity);
}
@Stateless
@Local(CrudService.class)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public class CrudServiceBean implements CrudService {
public static final String PERSISTENCE_UNIT_NAME = "my_persistence_unit";
private EntityManager entityManager;
@PersistenceContext(unitName = PERSISTENCE_UNIT_NAME)
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public void persist(Object entity) {
this.entityManager.persist(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下汇编程序:
public class FirstAssembler extends AbstractAssembler<FirstEntity> {
public FirstEntity transformToEntity(FirstValue value) {
if (value == null)
return null;
FirstEntity entity = new FirstEntity();
transformAbstractValueToAbstractObject(value, entity);
entity.setFixedRate(value.getFixedRate());
entity.setStartDate(value.getStartDate());
return entity;
}
}
public class SecondAssembler extends AbstractAssembler<SecondEntity> {
public SecondEntity transformToEntity(SecondValue value) {
if (value == null)
return null;
SecondEntity entity = new SecondEntity();
transformAbstractValueToAbstractObject(value, entity);
entity.setTransactionType(value.getTransactionType());
entity.setValueDate(value.getValueDate());
return entity;
}
}
public abstract class AbstractAssembler<T extends AbstractEntity> {
protected void transformAbstractValueToAbstractObject(AbstractValue value, T object) {
object.setUniqueId(value.getUniqueId());
object.setNominalAmountValue(value.getNominalAmountValue());
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下实体:
@Entity
public class FirstEntity extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ID")
private Long id;
@Column(name = "START_DATE")
@Temporal(TemporalType.DATE)
private Date startDate;
@Column(name = "FIXED_RATE")
@Digits(integer = 1, fraction = 10)
private BigDecimal fixedRate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public BigDecimal getFixedRate() {
return fixedRate;
}
public void setFixedRate(BigDecimal fixedRate) {
this.fixedRate = fixedRate;
}
}
@Entity
public class SecondEntity extends AbstractEntity {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ID")
private Long id;
@Column(name = "VALUE_DATE")
@Temporal(TemporalType.DATE)
private Date valueDate;
@Column(name = "TRANSACTION_TYPE")
@Enumerated(EnumType.STRING)
private TransactionType transactionType;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getValueDate() {
return valueDate;
}
public void setValueDate(Date valueDate) {
this.valueDate = valueDate;
}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
}
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "TRANSACTION_NOM_AMOUNT_VALUE")
@Digits(integer = 18, fraction = 5)
@Min(0)
private BigDecimal nominalAmountValue;
public BigDecimal getNominalAmountValue() {
return nominalAmountValue;
}
public void setNominalAmountValue(BigDecimal nominalAmountValue) {
this.nominalAmountValue = nominalAmountValue;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了以下方法:
public class FacadeBean implements Facade {
@Inject
private Assembler assembler;
@Inject
private AssemblerFactory assemblerFactory;
@Override
public <T extends AbstractValue> void save(T value) {
Assembler assembler = assemblerFactory.createAssembler(value);
AbstractEntity entity = assembler.transformToEntity(value);
this.crudService.persist(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是AssemblerFactoryImpl和AssemblerImpl,我必须在其中执行instanceOf检查和转换...
另一个想法是让值知道使用哪个变换器(或如何变换).但我希望价值"愚蠢".
@Glenn Lane
public AbstractValue save(AbstractValue value) {
AbstractAssembler<AbstractValue, AbstractEntity> assembler = new FirstAssembler();
AbstractEntity entity = assembler.transformToEntity(value);
AbstractValue result = assembler.transformToValue(entity);
return result;
}
Run Code Online (Sandbox Code Playgroud)
不起作用,因为
类型不匹配:无法从FirstAssembler转换为AbstractAssembler
使用带有绑定类型参数的泛型方法可以避免重复:
public <T extends AbstractValue> T save(T value) {...}
在方法主体中,您将能够使用value与AbstractValue.
笔记
save方法在本示例中似乎被覆盖,因此您可能还需要更改父类或接口的设计。