(ฉันเคยเห็นคำถามนี้แต่คำตอบแรกเป็นเรื่องเกี่ยวกับคุณสมบัติอัตโนมัติมากกว่าเกี่ยวกับการออกแบบและคำตอบที่สองบอกว่าซ่อนรหัสการจัดเก็บข้อมูลจากผู้บริโภคซึ่งฉันไม่แน่ใจว่าเป็นสิ่งที่ฉันต้องการ / รหัสของฉันทำ ดังนั้นฉันต้องการฟังความเห็นอื่น ๆ )
ฉันมีเอนทิตีที่คล้ายกันมากสองรายการHolidayDiscount
และRentalDiscount
นั่นคือส่วนลดที่มีความยาวเนื่องจาก 'ถ้าอย่างน้อยที่สุดจะnumberOfDays
ใช้percent
ส่วนลดได้' ตารางมี fks ไปยังเอนทิตีพาเรนต์ที่แตกต่างกันและใช้ในสถานที่ต่าง ๆ แต่ที่ที่ใช้จะมีตรรกะทั่วไปเพื่อรับส่วนลดสูงสุดที่เกี่ยวข้อง ตัวอย่างเช่น a HolidayOffer
มีจำนวนHolidayDiscounts
และเมื่อคำนวณต้นทุนเราต้องหาส่วนลดที่เกี่ยวข้อง RentalDiscounts
เหมือนกันสำหรับเช่าและ
เนื่องจากตรรกะเหมือนกันฉันต้องการเก็บไว้ในที่เดียว นั่นคือสิ่งที่วิธีต่อไปนี้เพรดิเคตและตัวเปรียบเทียบทำ:
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());
}
}
เนื่องจากข้อมูลที่จำเป็นเท่านั้นคือจำนวนวันฉันจึงสิ้นสุดด้วยส่วนต่อประสานเป็น
public interface LengthDiscount {
Integer getNumberOfDays();
}
และหน่วยงานทั้งสอง
@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;
}
}
อินเทอร์เฟซมีวิธีทะเยอทะยานเดียวที่ทั้งสองเอนทิตีใช้งานซึ่งแน่นอนว่าใช้งานได้ แต่ฉันสงสัยว่ามันเป็นการออกแบบที่ดี มันไม่ได้เป็นตัวแทนพฤติกรรมใด ๆ ที่ได้รับถือค่าไม่ใช่ทรัพย์สิน นี่เป็นกรณีที่ค่อนข้างง่ายฉันมีสองสามกรณีที่คล้ายกันและซับซ้อนมากขึ้น (ด้วย 3-4 getters)
คำถามของฉันคือนี่เป็นการออกแบบที่ไม่ดีหรือไม่? แนวทางที่ดีกว่าคืออะไร?