以核心域开始开发——自动售货机模型。首先创建Spring boot项目:

    1. 点击链接Spring Initializer
    2. 选择Gradle Project->Java->Spring boot版本2.4.4
    3. group namecom.lugewartifact namespring-boot-ddd
    4. 添加三个依赖JPARestRepositoriesH2
    5. 点击生成并导入。

    如图:
    image.png
    之后自动生成。项目结构如图:
    image.png
    生成代码如下:

    1. package com.lugew.springbootddd;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. @SpringBootApplication
    5. public class SpringBootDddApplication {
    6. public static void main(String[] args) {
    7. SpringApplication.run(SpringBootDddApplication.class, args);
    8. }
    9. }

    build.gradle

    1. plugins {
    2. id 'org.springframework.boot' version '2.4.3'
    3. id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    4. }
    5. ext {
    6. guavaVersion = "30.0-jre"
    7. spockVersion = "2.0-M4-groovy-3.0"
    8. groovyVersion = "3.0.6"
    9. lombokVersion = "1.18.16"
    10. openapiVersion = "1.5.2"
    11. byteBuddyVersion = "1.10.19"
    12. objenesisVersion = "3.1"
    13. }
    14. apply plugin: 'java'
    15. apply plugin: 'idea'
    16. apply plugin: 'java-library'
    17. group = 'com.lugew'
    18. version = '0.0.1-SNAPSHOT'
    19. sourceCompatibility = '11'
    20. targetCompatibility = '11'
    21. repositories {
    22. mavenLocal()
    23. maven {
    24. name '阿里云'
    25. url 'https://maven.aliyun.com/repository/public/'
    26. }
    27. mavenCentral()
    28. google()
    29. }
    30. test {
    31. useJUnitPlatform()
    32. }
    33. apply plugin: 'groovy'
    34. apply plugin: 'org.springframework.boot'
    35. apply plugin: 'io.spring.dependency-management'
    36. apply plugin: 'maven'
    37. dependencies {
    38. implementation(
    39. "com.google.guava:guava:${guavaVersion}",
    40. 'org.springframework.boot:spring-boot-starter',
    41. "org.springframework.boot:spring-boot-starter-web",
    42. "org.springframework.boot:spring-boot-starter-data-jpa",
    43. )
    44. runtimeOnly(
    45. "com.h2database:h2"
    46. )
    47. compileOnly(
    48. "org.projectlombok:lombok:${lombokVersion}"
    49. )
    50. annotationProcessor(
    51. "org.springframework.boot:spring-boot-configuration-processor",
    52. "org.projectlombok:lombok:${lombokVersion}"
    53. )
    54. testImplementation(
    55. "org.codehaus.groovy:groovy-all:${groovyVersion}",
    56. "org.codehaus.groovy:groovy:${groovyVersion}",
    57. "org.spockframework:spock-core:${spockVersion}",
    58. "net.bytebuddy:byte-buddy:${byteBuddyVersion}",
    59. "org.objenesis:objenesis:${objenesisVersion}",
    60. )
    61. }

    setting.gradle:

    1. rootProject.name = 'spring-boot-ddd'

    随后在springbootdd目录下创建snackmachine目录:
    image.png
    snackmachine下创建SnackMachine类:
    image.png

    1. package com.lugew.springbootddd.snackmachine;
    2. import lombok.Getter;
    3. import lombok.Setter;
    4. @Getter
    5. @Setter
    6. public final class SnackMachine {
    7. private int oneCentCount;
    8. private int tenCentCount;
    9. private int quarterCount;
    10. private int oneDollarCount;
    11. private int fiveDollarCount;
    12. private int twentyDollarCount;
    13. public void insertMoney(int oneCentCount,
    14. int tenCentCount,
    15. int quarterCount,
    16. int oneDollarCount,
    17. int fiveDollarCount,
    18. int twentyDollarCount) {
    19. oneCentCount += oneCentCount;
    20. tenCentCount += tenCentCount;
    21. quarterCount += quarterCount;
    22. oneDollarCount += oneDollarCount;
    23. fiveDollarCount += fiveDollarCount;
    24. twentyDollarCount += twentyDollarCount;
    25. }
    26. public void returnMoney() {
    27. }
    28. }

    👆注意,此类使用final修饰符限定。我们使用字段记录当前售货机金额,并且引入insertMoney投币、returnMoney退币、buySnack购买零食功能。对SnackMachine类进一步改造:

    1. package com.lugew.springbootddd.snackmachine;
    2. import lombok.Getter;
    3. import lombok.Setter;
    4. @Getter
    5. @Setter
    6. public final class SnackMachine {
    7. private int oneCentCount;
    8. private int tenCentCount;
    9. private int quarterCount;
    10. private int oneDollarCount;
    11. private int fiveDollarCount;
    12. private int twentyDollarCount;
    13. private int oneCentCountInTransaction = 0;
    14. private int tenCentCountInTransaction = 0;
    15. private int quarterCountInTransaction = 0;
    16. private int oneDollarCountInTransaction = 0;
    17. private int fiveDollarCountInTransaction = 0;
    18. private int twentyDollarCountInTransaction = 0;
    19. public void insertMoney(int oneCentCount,
    20. int tenCentCount,
    21. int quarterCount,
    22. int oneDollarCount,
    23. int fiveDollarCount,
    24. int twentyDollarCount) {
    25. oneCentCountInTransaction += oneCentCount;
    26. tenCentCountInTransaction += tenCentCount;
    27. quarterCountInTransaction += quarterCount;
    28. oneDollarCountInTransaction += oneDollarCount;
    29. fiveDollarCountInTransaction += fiveDollarCount;
    30. twentyDollarCountInTransaction += twentyDollarCount;
    31. }
    32. public void returnMoney() {
    33. oneCentCountInTransaction = 0;
    34. tenCentCountInTransaction = 0;
    35. quarterCountInTransaction = 0;
    36. oneDollarCountInTransaction = 0;
    37. fiveDollarCountInTransaction = 0;
    38. twentyDollarCountInTransaction = 0;
    39. }
    40. public void buySnack() {
    41. oneCentCount += oneCentCountInTransaction;
    42. tenCentCount += tenCentCountInTransaction;
    43. quarterCount += quarterCountInTransaction;
    44. oneDollarCount += oneDollarCountInTransaction;
    45. fiveDollarCount += fiveDollarCountInTransaction;
    46. twentyDollarCount += twentyDollarCountInTransaction;
    47. oneCentCountInTransaction = 0;
    48. tenCentCountInTransaction = 0;
    49. quarterCountInTransaction = 0;
    50. oneDollarCountInTransaction = 0;
    51. fiveDollarCountInTransaction = 0;
    52. twentyDollarCountInTransaction = 0;
    53. }
    54. }

    InTransaction字段表示用户投币,当用户购买零食时,用户投币将被累加到机器账户,投币也将被清零。零食机的基本功能实现如上,在此基础上我们可以做进一步的改进,比如,我们可以将金额字段抽象于一个类Money中:

    1. package com.lugew.springbootddd.snackmachine;
    2. public class Money {
    3. private int oneCentCount;
    4. private int tenCentCount;
    5. private int quarterCount;
    6. private int oneDollarCount;
    7. private int fiveDollarCount;
    8. private int twentyDollarCount;
    9. public Money(int oneCentCount, int tenCentCount, int quarterCount, int
    10. oneDollarCount, int fiveDollarCount, int twentyDollarCount) {
    11. this.oneCentCount = oneCentCount;
    12. this.tenCentCount = tenCentCount;
    13. this.quarterCount = quarterCount;
    14. this.oneDollarCount = oneDollarCount;
    15. this.fiveDollarCount = fiveDollarCount;
    16. this.twentyDollarCount = twentyDollarCount;
    17. }
    18. public static Money add(Money money1, Money money2) {
    19. return new Money(
    20. money1.oneCentCount + money2.oneCentCount,
    21. money1.tenCentCount + money2.tenCentCount,
    22. money1.quarterCount + money2.quarterCount,
    23. money1.oneDollarCount + money2.oneDollarCount,
    24. money1.fiveDollarCount + money2.fiveDollarCount,
    25. money1.twentyDollarCount + money2.twentyDollarCount);
    26. }
    27. }

    不仅如此,Money类还内聚了add加法功能,从而SnackMachine类可以进一步简化:

    1. package com.lugew.springbootddd.snackmachine;
    2. import lombok.Getter;
    3. import lombok.Setter;
    4. @Getter
    5. @Setter
    6. public final class SnackMachine {
    7. private Money moneyInside;
    8. private Money moneyInTransaction;
    9. public void insertMoney(Money money) {
    10. moneyInTransaction = Money.add(moneyInTransaction, money);
    11. }
    12. public void returnMoney() {
    13. //moneyInTransaction = 0
    14. }
    15. public void buySnack() {
    16. moneyInside = Money.add(moneyInside, moneyInTransaction);
    17. //moneyInTransaction = 0
    18. }
    19. }

    👆可以看到SnackMachine更加精简了。