(Ho visto questa domanda , ma la prima risposta riguarda le proprietà automatiche più che sul design, e la seconda dice nasconde il codice di archiviazione dei dati dal consumatore , che io" Non sono sicuro di quello che voglio / il mio codice fa, quindi mi piacerebbe sentire qualche altra opinione)
Ho due entità molto simili, HolidayDiscount
e RentalDiscount
, che rappresentano sconti di lunghezza come "se dura almeno numberOfDays
, uno sconto percent
è applicabile". Le tabelle hanno fks per diverse entità padre e vengono utilizzate in luoghi diversi, ma dove vengono utilizzate, esiste una logica comune per ottenere lo sconto massimo applicabile. Ad esempio, un HolidayOffer
ha un numero di HolidayDiscounts
, e nel calcolare il suo costo, dobbiamo calcolare lo sconto applicabile. Lo stesso per noleggi e RentalDiscounts
.
Poiché la logica è la stessa, voglio mantenerla in un unico posto. Questo è ciò che fanno il seguente metodo, predicato e comparatore:
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());
}
}
Poiché le uniche informazioni necessarie sono il numero di giorni, finisco con un'interfaccia come
public interface LengthDiscount {
Integer getNumberOfDays();
}
E le due entità
@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;
}
}
L'interfaccia ha un unico metodo getter che le due entità implementano, che ovviamente funziona, ma dubito che sia un buon progetto. Non rappresenta alcun comportamento, dato che tenere un valore non è una proprietà. Questo è un caso piuttosto semplice, ho un paio di casi simili e più complessi (con getter di 3-4).
La mia domanda è, è un cattivo design? Qual è un approccio migliore?