(Tôi đã nhìn thấy câu hỏi này , nhưng câu trả lời đầu tiên đi về các thuộc tính tự động hơn về thiết kế, và một trong những thứ hai nói giấu mã lưu trữ dữ liệu từ người tiêu dùng , mà tôi không chắc chắn là những gì tôi muốn / mã của tôi không, vì vậy tôi muốn nghe một số ý kiến khác)
Tôi có hai thực thể rất giống nhau HolidayDiscount
và RentalDiscount
, đại diện cho giảm giá theo chiều dài là 'nếu nó kéo dài ít nhất numberOfDays
, percent
giảm giá được áp dụng'. Các bảng có fks cho các thực thể mẹ khác nhau và được sử dụng ở những nơi khác nhau, nhưng khi chúng được sử dụng, có một logic chung để được giảm giá tối đa áp dụng. Chẳng hạn, a HolidayOffer
có một số HolidayDiscounts
và khi tính chi phí của nó, chúng ta cần tính ra mức chiết khấu áp dụng. Tương tự cho thuê và RentalDiscounts
.
Vì logic là như nhau, tôi muốn giữ nó ở một nơi duy nhất. Đó là những gì phương pháp, vị ngữ và so sánh sau đây làm:
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());
}
}
Vì thông tin duy nhất cần là số ngày, tôi kết thúc với một giao diện như
public interface LengthDiscount {
Integer getNumberOfDays();
}
Và hai thực thể
@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;
}
}
Giao diện có một phương thức getter duy nhất mà hai thực thể thực hiện, tất nhiên là hoạt động, nhưng tôi nghi ngờ đó là một thiết kế tốt. Nó không đại diện cho bất kỳ hành vi nào, đưa ra một giá trị không phải là một tài sản. Đây là một trường hợp khá đơn giản, tôi có thêm một vài trường hợp tương tự, phức tạp hơn (với 3-4 getters).
Câu hỏi của tôi là, đây có phải là một thiết kế xấu? Một cách tiếp cận tốt hơn là gì?