(Ich habe diese Frage gesehen , aber die erste Antwort bezieht sich mehr auf automatische Eigenschaften als auf Design, und die zweite lautet: Verstecke den Datenspeichercode vor dem Verbraucher , was ich nicht sicher bin, was ich will / mein Code tut. also würde ich gerne eine andere Meinung hören)
Ich habe zwei sehr ähnliche Einheiten, HolidayDiscount
und RentalDiscount
, die Länge Rabatte als repräsentieren ‚ wenn es mindestens dauert numberOfDays
, eine percent
Ermäßigung gilt‘. Die Tabellen haben fks für verschiedene übergeordnete Entitäten und werden an verschiedenen Orten verwendet. Wo sie jedoch verwendet werden, gibt es eine gemeinsame Logik, um den maximal anwendbaren Rabatt zu erhalten. Zum Beispiel HolidayOffer
hat a eine Reihe von HolidayDiscounts
, und bei der Berechnung seiner Kosten müssen wir den anwendbaren Rabatt herausfinden. Gleiches gilt für Vermietung und RentalDiscounts
.
Da die Logik dieselbe ist, möchte ich sie an einem einzigen Ort aufbewahren. Das tun die folgende Methode, das folgende Prädikat und der folgende Komparator:
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());
}
}
Da nur die Anzahl der Tage benötigt wird, erhalte ich eine Schnittstelle als
public interface LengthDiscount {
Integer getNumberOfDays();
}
Und die beiden Einheiten
@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;
}
}
Die Schnittstelle hat eine Single-Getter-Methode, die die beiden Entitäten implementieren, was natürlich funktioniert, aber ich bezweifle, dass es ein gutes Design ist. Es stellt kein Verhalten dar, da das Halten eines Werts keine Eigenschaft ist. Dies ist ein ziemlich einfacher Fall, ich habe noch ein paar ähnliche, komplexere Fälle (mit 3-4 Gettern).
Meine Frage ist, ist das ein schlechtes Design? Was ist ein besserer Ansatz?