重构代码,结合UI、Controller和Repository:

    1. package com.lugew.springbootddd.snackmachine;
    2. import com.lugew.springbootddd.Entity;
    3. import com.lugew.springbootddd.SnackMachineDto;
    4. import lombok.Getter;
    5. import lombok.Setter;
    6. import java.util.Arrays;
    7. import static com.lugew.springbootddd.snackmachine.Money.None;
    8. @Getter
    9. @Setter
    10. public final class SnackMachine extends Entity {
    11. private Money moneyInside;
    12. private Money moneyInTransaction;
    13. public SnackMachine() {
    14. moneyInside = None;
    15. moneyInTransaction = None;
    16. }
    17. public void insertMoney(Money money) {
    18. Money[] coinsAndNotes = {Money.Cent, Money.TenCent, Money.Quarter,
    19. Money.Dollar, Money.FiveDollar,
    20. Money.TwentyDollar};
    21. if (!Arrays.asList(coinsAndNotes).contains(money))
    22. throw new IllegalStateException();
    23. moneyInTransaction = Money.add(moneyInTransaction, money);
    24. }
    25. public void returnMoney() {
    26. moneyInTransaction = None;
    27. }
    28. public void buySnack() {
    29. moneyInside = Money.add(moneyInside, moneyInTransaction);
    30. moneyInTransaction = None;
    31. }
    32. public SnackMachineDto convertToSnackMachineDto() {
    33. SnackMachineDto snackMachineDto = new SnackMachineDto();
    34. snackMachineDto.setId(id);
    35. snackMachineDto.setMoneyInTransaction(moneyInTransaction.getAmount());
    36. snackMachineDto.setOneCentCount(moneyInside.getOneCentCount());
    37. snackMachineDto.setTenCentCount(moneyInside.getTenCentCount());
    38. snackMachineDto.setQuarterCount(moneyInside.getQuarterCount());
    39. snackMachineDto.setOneDollarCount(moneyInside.getOneDollarCount());
    40. snackMachineDto.setFiveDollarCount(moneyInside.getFiveDollarCount());
    41. snackMachineDto.setTwentyDollarCount(moneyInside.getTwentyDollarCount());
    42. return snackMachineDto;
    43. }
    44. }
    1. package com.lugew.springbootddd;
    2. import com.lugew.springbootddd.snackmachine.Money;
    3. import com.lugew.springbootddd.snackmachine.SnackMachine;
    4. import lombok.RequiredArgsConstructor;
    5. import org.springframework.web.bind.annotation.*;
    6. import static com.lugew.springbootddd.snackmachine.Money.*;
    7. /**
    8. * @author 夏露桂
    9. * @since 2021/6/10 11:55
    10. */
    11. @RestController
    12. @RequestMapping("snackmachines")
    13. @RequiredArgsConstructor
    14. public class SnackMachineController {
    15. private final SnackMachineRepository snackMachineRepository;
    16. @GetMapping("/{id}")
    17. @ResponseBody
    18. public SnackMachineDto getSnackMachine(@PathVariable("id") long id) {
    19. return snackMachineRepository.findById(id).orElse(null);
    20. }
    21. @PutMapping("/{id}/{slotNumber}")
    22. public void buySnack(@PathVariable("id") long id, @PathVariable("slotNumber")
    23. int slotNumber) {
    24. SnackMachineDto snackMachineDto =
    25. snackMachineRepository.findById(id).orElse(null);
    26. SnackMachine snackMachine = snackMachineDto.convertToSnackMachine();
    27. snackMachine.buySnack();
    28. snackMachineRepository.save(snackMachine.convertToSnackMachineDto());
    29. }
    30. @PutMapping("/{id}/moneyInTransaction/{coinOrNote}")
    31. public void insertCoinOrNote(@PathVariable("id") long id, @PathVariable("coinOrNote") String coinOrNote) {
    32. SnackMachineDto snackMachineDto =
    33. snackMachineRepository.findById(id).orElse(null);
    34. SnackMachine snackMachine = snackMachineDto.convertToSnackMachine();
    35. if (coinOrNote.equalsIgnoreCase("Cent")) snackMachine.insertMoney(Cent);
    36. else if (coinOrNote.equalsIgnoreCase("TenCent"))
    37. snackMachine.insertMoney(TenCent);
    38. else if (coinOrNote.equalsIgnoreCase("Quarter"))
    39. snackMachine.insertMoney(Quarter);
    40. else if (coinOrNote.equalsIgnoreCase("Dollar"))
    41. snackMachine.insertMoney(Dollar);
    42. else if (coinOrNote.equalsIgnoreCase("FiveDollar"))
    43. snackMachine.insertMoney(FiveDollar);
    44. else if (coinOrNote.equalsIgnoreCase("TwentyDollar"))
    45. snackMachine.insertMoney(TwentyDollar);
    46. snackMachineRepository.save(snackMachine.convertToSnackMachineDto());
    47. }
    48. @PutMapping("/{id}/moneyInTransaction")
    49. public void returnMoney(@PathVariable("id") long id) {
    50. SnackMachineDto snackMachineDto =
    51. snackMachineRepository.findById(id).orElse(null);
    52. SnackMachine snackMachine = snackMachineDto.convertToSnackMachine();
    53. snackMachine.returnMoney();
    54. snackMachineRepository.save(snackMachine.convertToSnackMachineDto());
    55. }
    56. public Money getWholeMoney(SnackMachine snackMachine) {
    57. return Money.add(snackMachine.getMoneyInside(), snackMachine.getMoneyInTransaction());
    58. }
    59. }
    1. package com.lugew.springbootddd;
    2. import com.lugew.springbootddd.snackmachine.Money;
    3. import com.lugew.springbootddd.snackmachine.SnackMachine;
    4. import lombok.Getter;
    5. import lombok.Setter;
    6. import javax.persistence.Entity;
    7. import javax.persistence.GeneratedValue;
    8. import javax.persistence.Id;
    9. /**
    10. * @author 夏露桂
    11. * @since 2021/6/10 12:00
    12. */
    13. @Getter
    14. @Setter
    15. @Entity
    16. public class SnackMachineDto {
    17. @Id
    18. @GeneratedValue
    19. private long id;
    20. private int oneCentCount;
    21. private int tenCentCount;
    22. private int quarterCount;
    23. private int oneDollarCount;
    24. private int fiveDollarCount;
    25. private int twentyDollarCount;
    26. private float moneyInTransaction;
    27. public SnackMachine convertToSnackMachine() {
    28. SnackMachine snackMachine = new SnackMachine();
    29. snackMachine.setId(id);
    30. snackMachine.setMoneyInTransaction(convertAmountToMoney());
    31. snackMachine.setMoneyInside(new
    32. Money(oneCentCount, tenCentCount, quarterCount, oneDollarCount, fiveDollarCount, twentyDollarCount));
    33. return snackMachine;
    34. }
    35. private Money convertAmountToMoney() {
    36. float amount = this.moneyInTransaction;
    37. int twentyDollarCount = (int) (amount / 20f);
    38. amount %= 20f;
    39. int fiveDollarCount = (int) (amount / 5f);
    40. amount %= 5f;
    41. int oneDollarCount = (int) (amount);
    42. amount %= 1f;
    43. int quarterCount = (int) (amount / 0.25f);
    44. amount %= 0.25f;
    45. int tenCentCount = (int) (amount / 0.10f);
    46. amount %= 0.10f;
    47. int oneCentCount = (int) (amount / 0.01f);
    48. return new Money(this.moneyInTransaction, oneCentCount, tenCentCount, quarterCount, oneDollarCount, fiveDollarCount, twentyDollarCount);
    49. }
    50. }
    1. package com.lugew.springbootddd.snackmachine;
    2. import com.lugew.springbootddd.ValueObject;
    3. import lombok.Getter;
    4. /**
    5. * @author 夏露桂
    6. * @since 2021/6/7 11:59
    7. */
    8. @Getter
    9. public class Money extends ValueObject<Money> {
    10. public static Money None = new Money(0, 0, 0, 0, 0, 0);
    11. public static Money Cent = new Money(1, 0, 0, 0, 0, 0);
    12. public static Money TenCent = new Money(0, 1, 0, 0, 0, 0);
    13. public static Money Quarter = new Money(0, 0, 1, 0, 0, 0);
    14. public static Money Dollar = new Money(0, 0, 0, 1, 0, 0);
    15. public static Money FiveDollar = new Money(0, 0, 0, 0, 1, 0);
    16. public static Money TwentyDollar = new Money(0, 0, 0, 0, 0, 1);
    17. private final int oneCentCount;
    18. private final int tenCentCount;
    19. private final int quarterCount;
    20. private final int oneDollarCount;
    21. private final int fiveDollarCount;
    22. private final int twentyDollarCount;
    23. private float amount;
    24. public float getAmount() {
    25. return oneCentCount * 0.01f + tenCentCount * 0.10f + quarterCount * 0.25f +
    26. oneDollarCount * 1f
    27. + fiveDollarCount * 5f + twentyDollarCount * 20f;
    28. }
    29. public Money(int oneCentCount, int tenCentCount, int quarterCount, int
    30. oneDollarCount, int fiveDollarCount, int twentyDollarCount) {
    31. if (oneCentCount < 0)
    32. throw new IllegalStateException();
    33. if (tenCentCount < 0)
    34. throw new IllegalStateException();
    35. if (quarterCount < 0)
    36. throw new IllegalStateException();
    37. if (oneDollarCount < 0)
    38. throw new IllegalStateException();
    39. if (fiveDollarCount < 0)
    40. throw new IllegalStateException();
    41. if (twentyDollarCount < 0)
    42. throw new IllegalStateException();
    43. this.oneCentCount = oneCentCount;
    44. this.tenCentCount = tenCentCount;
    45. this.quarterCount = quarterCount;
    46. this.oneDollarCount = oneDollarCount;
    47. this.fiveDollarCount = fiveDollarCount;
    48. this.twentyDollarCount = twentyDollarCount;
    49. }
    50. public Money(float amount, int oneCentCount, int tenCentCount, int quarterCount, int
    51. oneDollarCount, int fiveDollarCount, int twentyDollarCount) {
    52. this(oneCentCount, tenCentCount, quarterCount, oneDollarCount, fiveDollarCount, twentyDollarCount);
    53. if (amount < 0) {
    54. throw new IllegalStateException();
    55. }
    56. this.amount = amount;
    57. }
    58. public Money substract(Money other) {
    59. return new Money(
    60. oneCentCount - other.oneCentCount,
    61. tenCentCount - other.tenCentCount,
    62. quarterCount - other.quarterCount,
    63. oneDollarCount - other.oneDollarCount,
    64. fiveDollarCount - other.fiveDollarCount,
    65. twentyDollarCount - other.twentyDollarCount);
    66. }
    67. public static Money add(Money money1, Money money2) {
    68. return new Money(
    69. money1.oneCentCount + money2.oneCentCount,
    70. money1.tenCentCount + money2.tenCentCount,
    71. money1.quarterCount + money2.quarterCount,
    72. money1.oneDollarCount + money2.oneDollarCount,
    73. money1.fiveDollarCount + money2.fiveDollarCount,
    74. money1.twentyDollarCount + money2.twentyDollarCount);
    75. }
    76. @Override
    77. protected boolean equalsCore(Money other) {
    78. return oneCentCount == other.oneCentCount
    79. && tenCentCount == other.tenCentCount
    80. && quarterCount == other.quarterCount
    81. && oneDollarCount == other.oneDollarCount
    82. && fiveDollarCount == other.fiveDollarCount
    83. && twentyDollarCount == other.twentyDollarCount;
    84. }
    85. @Override
    86. protected int getHashCodeCore() {
    87. int hashCode = oneCentCount;
    88. hashCode = (hashCode * 397) ^ tenCentCount;
    89. hashCode = (hashCode * 397) ^ quarterCount;
    90. hashCode = (hashCode * 397) ^ oneDollarCount;
    91. hashCode = (hashCode * 397) ^ fiveDollarCount;
    92. hashCode = (hashCode * 397) ^ twentyDollarCount;
    93. return hashCode;
    94. }
    95. @Override
    96. public String toString() {
    97. if (getAmount() < 1)
    98. return "¢" + getAmount() * 100;
    99. return "$" + getAmount();
    100. }
    101. }
    1. package com.lugew.springbootddd;
    2. import org.springframework.data.repository.CrudRepository;
    3. /**
    4. * @author 夏露桂
    5. * @since 2021/6/15 10:50
    6. */
    7. public interface SnackMachineRepository extends CrudRepository<SnackMachineDto, Long> {
    8. }
    1. const rootURI = "http://localhost:23333/snackmachines/1";
    2. getSnackMachine();
    3. function getSnackMachine() {
    4. $.get(rootURI, function (data, status) {
    5. console.log(data)
    6. $('#moneyInserted').html(data.moneyInTransaction);
    7. $('#cent').html(data.moneyInside.oneCentCount);
    8. $('#tenCent').html(data.moneyInside.tenCentCount);
    9. $('#quarter').html(data.moneyInside.quarterCount);
    10. $('#dollar').html(data.moneyInside.oneDollarCount);
    11. $('#fiveDollar').html(data.moneyInside.fiveDollarCount);
    12. $('#twentyDollar').html(data.moneyInside.twentyDollarCount);
    13. });
    14. }
    15. $("button").click(function () {
    16. switch (this.id) {
    17. case "btnInsertCent" :
    18. insert("Cent")
    19. break;
    20. case "btnInsertTenCent" :
    21. insert("TenCent")
    22. break;
    23. case "btnInsertQuarter" :
    24. insert("Quarter")
    25. break;
    26. case "btnInsertDollar" :
    27. insert("Dollar")
    28. break;
    29. case "btnInsertFiveDollar" :
    30. insert("FiveDollar")
    31. break;
    32. case "btnInsertTwentyDollar" :
    33. insert("TwentyDollar")
    34. break;
    35. case "btnReturnMoney" :
    36. returnMoney()
    37. break;
    38. case "btnBuy" :
    39. buy("1")
    40. break;
    41. default :
    42. break;
    43. }
    44. });
    45. function insert(coinOrNote) {
    46. $.ajax({
    47. url: rootURI + '/moneyInTransaction/' + coinOrNote,
    48. type: 'PUT',
    49. success: function (result) {
    50. // Do something with the result
    51. }
    52. });
    53. location.reload();
    54. }
    55. function returnMoney() {
    56. $.ajax({
    57. url: rootURI + '/moneyInTransaction',
    58. type: 'PUT',
    59. success: function (result) {
    60. // Do something with the result
    61. }
    62. });
    63. location.reload();
    64. }
    65. function buy(position) {
    66. $.ajax({
    67. url: rootURI + '/' + position,
    68. type: 'PUT',
    69. success: function (result) {
    70. }
    71. });
    72. location.reload();
    73. }

    再次运行程序就能看到投币、退币和购买功能正常使用:

    上述代码有几处缺陷,比如amount转换精度会出现问题,简单起见,这里不做修复,感兴趣的读者可自行重构。