(He visto esta pregunta , pero la primera respuesta trata sobre las propiedades automáticas más que sobre el diseño, y la segunda dice que esconda el código de almacenamiento de datos del consumidor , lo que no estoy seguro es lo que quiero / mi código hace, así que me gustaría escuchar alguna otra opinión)
Tengo dos entidades muy similares HolidayDiscounty RentalDiscountque representan descuentos por duración como "si dura al menos numberOfDays, percentse aplica un descuento". Las tablas tienen fks para diferentes entidades principales y se usan en diferentes lugares, pero donde se usan, existe una lógica común para obtener el descuento máximo aplicable. Por ejemplo, a HolidayOffertiene una cantidad de HolidayDiscounts, y al calcular su costo, necesitamos calcular el descuento aplicable. Lo mismo para alquileres y RentalDiscounts.
Como la lógica es la misma, quiero mantenerla en un solo lugar. Eso es lo que hacen el siguiente método, predicado y comparador:
Optional<LengthDiscount> getMaxApplicableLengthDiscount(List<LengthDiscount> discounts, int daysToStay) {
if (discounts.isEmpty()) {
return Optional.empty();
}
return discounts.stream()
.filter(new DiscountIsApplicablePredicate(daysToStay))
.max(new DiscountMinDaysComparator());
}
public class DiscountIsApplicablePredicate implements Predicate<LengthDiscount> {
private final long daysToStay;
public DiscountIsApplicablePredicate(long daysToStay) {
this.daysToStay = daysToStay;
}
@Override
public boolean test(LengthDiscount discount) {
return daysToStay >= discount.getNumberOfDays();
}
}
public class DiscountMinDaysComparator implements Comparator<LengthDiscount> {
@Override
public int compare(LengthDiscount d1, LengthDiscount d2) {
return d1.getNumberOfDays().compareTo(d2.getNumberOfDays());
}
}
Como la única información necesaria es la cantidad de días, termino con una interfaz como
public interface LengthDiscount {
Integer getNumberOfDays();
}
Y las dos entidades
@Entity
@Table(name = "holidayDiscounts")
@Setter
public class HolidayDiscount implements LengthDiscount {
private BigInteger percent;
private Integer numberOfDays;
public BigInteger getPercent() {
return percent;
}
@Override
public Integer getNumberOfDays() {
return numberOfDays;
}
}
@Entity
@Table(name = "rentalDiscounts")
@Setter
public class RentalDiscount implements LengthDiscount {
private BigInteger percent;
private Integer numberOfDays;
public BigInteger getPercent() {
return percent;
}
@Override
public Integer getNumberOfDays() {
return numberOfDays;
}
}
La interfaz tiene un único método getter que implementan las dos entidades, que por supuesto funciona, pero dudo que sea un buen diseño. No representa ningún comportamiento, dado que mantener un valor no es una propiedad. Este es un caso bastante simple, tengo un par más de casos similares y más complejos (con 3-4 captadores).
Mi pregunta es, ¿es este un mal diseño? ¿Cuál es un mejor enfoque?