• 无ID属性
    • 判断相等的方法只能是抽象方法

    值对象没有ID属性,也就没有对应字段,这意味着我们没办法在基类中判断两个值对象是否相等。为了判断其结构相等,我们可以在基类中构建基础方法:

    1. package com.lugew.springbootddd;
    2. /**
    3. * @author 夏露桂
    4. * @since 2021/6/8 17:40
    5. */
    6. public abstract class ValueObject<T> {
    7. @Override
    8. public boolean equals(Object obj) {
    9. T valueObject = (T) obj;
    10. if (valueObject == null)
    11. return false;
    12. return equalsCore(valueObject);
    13. }
    14. @Override
    15. public int hashCode() {
    16. return getHashCodeCore();
    17. }
    18. protected abstract boolean equalsCore(T other);
    19. protected abstract int getHashCodeCore();
    20. }

    可以看到我们重写了equalshashCode方法,并且将具体的实现委托给了其子类。此时,我们可以将Money类进行重构:

    1. package com.lugew.springbootddd.snackmachine;
    2. import com.lugew.springbootddd.ValueObject;
    3. /**
    4. * @author 夏露桂
    5. * @since 2021/6/7 11:59
    6. */
    7. public class Money extends ValueObject<Money> {
    8. private final int oneCentCount;
    9. private final int tenCentCount;
    10. private final int quarterCount;
    11. private final int oneDollarCount;
    12. private final int fiveDollarCount;
    13. private final int twentyDollarCount;
    14. public Money(int oneCentCount, int tenCentCount, int quarterCount, int
    15. oneDollarCount, int fiveDollarCount, int twentyDollarCount) {
    16. this.oneCentCount = oneCentCount;
    17. this.tenCentCount = tenCentCount;
    18. this.quarterCount = quarterCount;
    19. this.oneDollarCount = oneDollarCount;
    20. this.fiveDollarCount = fiveDollarCount;
    21. this.twentyDollarCount = twentyDollarCount;
    22. }
    23. public static Money add(Money money1, Money money2) {
    24. return new Money(
    25. money1.oneCentCount + money2.oneCentCount,
    26. money1.tenCentCount + money2.tenCentCount,
    27. money1.quarterCount + money2.quarterCount,
    28. money1.oneDollarCount + money2.oneDollarCount,
    29. money1.fiveDollarCount + money2.fiveDollarCount,
    30. money1.twentyDollarCount + money2.twentyDollarCount);
    31. }
    32. @Override
    33. protected boolean equalsCore(Money other) {
    34. return oneCentCount == other.oneCentCount
    35. && tenCentCount == other.tenCentCount
    36. && quarterCount == other.quarterCount
    37. && oneDollarCount == other.oneDollarCount
    38. && fiveDollarCount == other.fiveDollarCount
    39. && twentyDollarCount == other.twentyDollarCount;
    40. }
    41. @Override
    42. protected int getHashCodeCore() {
    43. int hashCode = oneCentCount;
    44. hashCode = (hashCode * 397) ^ tenCentCount;
    45. hashCode = (hashCode * 397) ^ quarterCount;
    46. hashCode = (hashCode * 397) ^ oneDollarCount;
    47. hashCode = (hashCode * 397) ^ fiveDollarCount;
    48. hashCode = (hashCode * 397) ^ twentyDollarCount;
    49. return hashCode;
    50. }
    51. }

    父类的抽象方法equalsCoregetHashCodeCore子类是必须实现的。equalsCore根据每个字段的值来判断两个值对象是否相等。
    image.png
    在这里,我再次重申实体和值对象的区别:实体ID相等而值对象结构相等,值对象不存在ID字段。