以核心域开始开发——自动售货机模型。首先创建Spring boot
项目:
- 点击链接
Spring Initializer
。 - 选择
Gradle Project->Java->Spring boot
版本2.4.4
。 group name
为com.lugew
,artifact name
为spring-boot-ddd
。- 添加三个依赖
JPA
、RestRepositories
和H2
。 - 点击生成并导入。
如图:
之后自动生成。项目结构如图:
生成代码如下:
package com.lugew.springbootddd;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootDddApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDddApplication.class, args);
}
}
build.gradle
plugins {
id 'org.springframework.boot' version '2.4.3'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
}
ext {
guavaVersion = "30.0-jre"
spockVersion = "2.0-M4-groovy-3.0"
groovyVersion = "3.0.6"
lombokVersion = "1.18.16"
openapiVersion = "1.5.2"
byteBuddyVersion = "1.10.19"
objenesisVersion = "3.1"
}
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'java-library'
group = 'com.lugew'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
targetCompatibility = '11'
repositories {
mavenLocal()
maven {
name '阿里云'
url 'https://maven.aliyun.com/repository/public/'
}
mavenCentral()
google()
}
test {
useJUnitPlatform()
}
apply plugin: 'groovy'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'maven'
dependencies {
implementation(
"com.google.guava:guava:${guavaVersion}",
'org.springframework.boot:spring-boot-starter',
"org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-data-jpa",
)
runtimeOnly(
"com.h2database:h2"
)
compileOnly(
"org.projectlombok:lombok:${lombokVersion}"
)
annotationProcessor(
"org.springframework.boot:spring-boot-configuration-processor",
"org.projectlombok:lombok:${lombokVersion}"
)
testImplementation(
"org.codehaus.groovy:groovy-all:${groovyVersion}",
"org.codehaus.groovy:groovy:${groovyVersion}",
"org.spockframework:spock-core:${spockVersion}",
"net.bytebuddy:byte-buddy:${byteBuddyVersion}",
"org.objenesis:objenesis:${objenesisVersion}",
)
}
setting.gradle
:
rootProject.name = 'spring-boot-ddd'
随后在springbootdd目录下创建snackmachine目录:
snackmachine下创建SnackMachine类:
package com.lugew.springbootddd.snackmachine;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public final class SnackMachine {
private int oneCentCount;
private int tenCentCount;
private int quarterCount;
private int oneDollarCount;
private int fiveDollarCount;
private int twentyDollarCount;
public void insertMoney(int oneCentCount,
int tenCentCount,
int quarterCount,
int oneDollarCount,
int fiveDollarCount,
int twentyDollarCount) {
oneCentCount += oneCentCount;
tenCentCount += tenCentCount;
quarterCount += quarterCount;
oneDollarCount += oneDollarCount;
fiveDollarCount += fiveDollarCount;
twentyDollarCount += twentyDollarCount;
}
public void returnMoney() {
}
}
👆注意,此类使用final
修饰符限定。我们使用字段记录当前售货机金额,并且引入insertMoney
投币、returnMoney
退币、buySnack
购买零食功能。对SnackMachine
类进一步改造:
package com.lugew.springbootddd.snackmachine;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public final class SnackMachine {
private int oneCentCount;
private int tenCentCount;
private int quarterCount;
private int oneDollarCount;
private int fiveDollarCount;
private int twentyDollarCount;
private int oneCentCountInTransaction = 0;
private int tenCentCountInTransaction = 0;
private int quarterCountInTransaction = 0;
private int oneDollarCountInTransaction = 0;
private int fiveDollarCountInTransaction = 0;
private int twentyDollarCountInTransaction = 0;
public void insertMoney(int oneCentCount,
int tenCentCount,
int quarterCount,
int oneDollarCount,
int fiveDollarCount,
int twentyDollarCount) {
oneCentCountInTransaction += oneCentCount;
tenCentCountInTransaction += tenCentCount;
quarterCountInTransaction += quarterCount;
oneDollarCountInTransaction += oneDollarCount;
fiveDollarCountInTransaction += fiveDollarCount;
twentyDollarCountInTransaction += twentyDollarCount;
}
public void returnMoney() {
oneCentCountInTransaction = 0;
tenCentCountInTransaction = 0;
quarterCountInTransaction = 0;
oneDollarCountInTransaction = 0;
fiveDollarCountInTransaction = 0;
twentyDollarCountInTransaction = 0;
}
public void buySnack() {
oneCentCount += oneCentCountInTransaction;
tenCentCount += tenCentCountInTransaction;
quarterCount += quarterCountInTransaction;
oneDollarCount += oneDollarCountInTransaction;
fiveDollarCount += fiveDollarCountInTransaction;
twentyDollarCount += twentyDollarCountInTransaction;
oneCentCountInTransaction = 0;
tenCentCountInTransaction = 0;
quarterCountInTransaction = 0;
oneDollarCountInTransaction = 0;
fiveDollarCountInTransaction = 0;
twentyDollarCountInTransaction = 0;
}
}
InTransaction
字段表示用户投币,当用户购买零食时,用户投币将被累加到机器账户,投币也将被清零。零食机的基本功能实现如上,在此基础上我们可以做进一步的改进,比如,我们可以将金额字段抽象于一个类Money
中:
package com.lugew.springbootddd.snackmachine;
public class Money {
private int oneCentCount;
private int tenCentCount;
private int quarterCount;
private int oneDollarCount;
private int fiveDollarCount;
private int twentyDollarCount;
public Money(int oneCentCount, int tenCentCount, int quarterCount, int
oneDollarCount, int fiveDollarCount, int twentyDollarCount) {
this.oneCentCount = oneCentCount;
this.tenCentCount = tenCentCount;
this.quarterCount = quarterCount;
this.oneDollarCount = oneDollarCount;
this.fiveDollarCount = fiveDollarCount;
this.twentyDollarCount = twentyDollarCount;
}
public static Money add(Money money1, Money money2) {
return new Money(
money1.oneCentCount + money2.oneCentCount,
money1.tenCentCount + money2.tenCentCount,
money1.quarterCount + money2.quarterCount,
money1.oneDollarCount + money2.oneDollarCount,
money1.fiveDollarCount + money2.fiveDollarCount,
money1.twentyDollarCount + money2.twentyDollarCount);
}
}
不仅如此,Money
类还内聚了add
加法功能,从而SnackMachine
类可以进一步简化:
package com.lugew.springbootddd.snackmachine;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public final class SnackMachine {
private Money moneyInside;
private Money moneyInTransaction;
public void insertMoney(Money money) {
moneyInTransaction = Money.add(moneyInTransaction, money);
}
public void returnMoney() {
//moneyInTransaction = 0
}
public void buySnack() {
moneyInside = Money.add(moneyInside, moneyInTransaction);
//moneyInTransaction = 0
}
}
👆可以看到SnackMachine
更加精简了。