本篇文章采用了状态模式实现了单据状态的相互变化(草稿、待审核、已审核、已撤销等等)。
单据(草稿)-> 提交操作 -> 单据(待审核)-> 审核操作 -> 单据(已审核)-> 弃审操作 -> 单据(草稿)
当单据处于【待审核】状态时,进行删除操作时,不是可行的,只可进行审核操作或者撤回操作。
# 引入依赖
<dependencies> | |
<dependency> | |
<groupId>javax.validation</groupId> | |
<artifactId>validation-api</artifactId> | |
<version>2.0.1.Final</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-web</artifactId> | |
<version>2.6.6</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter</artifactId> | |
<version>2.6.6</version> | |
</dependency> | |
<dependency> | |
<groupId>org.junit.jupiter</groupId> | |
<artifactId>junit-jupiter-api</artifactId> | |
<version>5.8.2</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-test</artifactId> | |
<version>2.6.6</version> | |
</dependency> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-test</artifactId> | |
<version>5.3.18</version> | |
</dependency> | |
</dependencies> |
# 单据实体类
package com.example.demo.entity; | |
import com.example.demo.dto.Type; | |
import io.swagger.annotations.ApiModelProperty; | |
import io.swagger.annotations.ApiOperation; | |
@ApiOperation(value = "单据实体") | |
public class DemoOrderEntity { | |
@ApiModelProperty(value = "单据编码") | |
private String code; | |
@ApiModelProperty(value = "单据状态") | |
private Type status; | |
} |
# 常量类
Type
package com.example.demo.dto; | |
public class Type { | |
private String code; | |
private String name; | |
public Type(String code, String name) { | |
this.code = code; | |
this.name = name; | |
} | |
} |
Status
package com.example.demo.constant; | |
import com.example.demo.dto.Type; | |
public enum Status { | |
DRAFT("DRAFT", "草稿"), | |
WAIT("WAIT", "待审核"), | |
COMPLETE("COMPLETE", "已审核"), | |
CANCEL("CANCEL", "已作废"), | |
; | |
private String code; | |
private String name; | |
Status(String code, String name) { | |
this.code = code; | |
this.name = name; | |
} | |
public String getCode() { | |
return code; | |
} | |
public String getName() { | |
return name; | |
} | |
public Type toType(){ | |
return new Type(this.code, this.name); | |
} | |
} |
# 数据层
package com.example.demo.dao; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.springframework.stereotype.Component; | |
import java.util.HashMap; | |
import java.util.Map; | |
@Component | |
public class DemoOrderDao { | |
private static final Map<String, DemoOrderEntity> map = new HashMap<>(); | |
public DemoOrderEntity add(DemoOrderEntity demoOrderEntity){ | |
map.put(demoOrderEntity.getCode(), demoOrderEntity); | |
return demoOrderEntity; | |
} | |
public DemoOrderEntity findByCode(String code){ | |
return map.get(code); | |
} | |
public void remove(DemoOrderEntity demoOrderEntity) { | |
map.remove(demoOrderEntity.getCode()); | |
} | |
} |
# 状态管理机
DemoOrderState
package com.example.demo.helper; | |
import com.example.demo.entity.DemoOrderEntity; | |
/** | |
* 单据状态机接口 | |
*/ | |
public interface DemoOrderState { | |
// 保存 | |
DemoOrderEntity draft(DemoOrderEntity demoOrderEntity); | |
// 提交 | |
DemoOrderEntity submit(DemoOrderEntity demoOrderEntity); | |
// 审核 | |
DemoOrderEntity approve(DemoOrderEntity demoOrderEntity); | |
// 弃审 | |
DemoOrderEntity unApprove(DemoOrderEntity demoOrderEntity); | |
// 撤销 | |
DemoOrderEntity revoke(DemoOrderEntity demoOrderEntity); | |
// 作废 | |
DemoOrderEntity cancel(DemoOrderEntity demoOrderEntity); | |
// 删除 | |
void remove(DemoOrderEntity demoOrderEntity); | |
} |
AbstractDemoOrderState
package com.example.demo.helper; | |
import com.example.demo.dao.DemoOrderDao; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import javax.annotation.PostConstruct; | |
import javax.validation.ValidationException; | |
/** | |
* 状态抽象类 | |
*/ | |
public abstract class AbstractDemoOrderState implements DemoOrderState{ | |
@Autowired | |
protected DemoOrderDao demoOrderDao; | |
@PostConstruct | |
void register(){ | |
DemoOrderStateManage.getInstance().register(getStatusForRegister(), this); | |
} | |
protected abstract String getStatusForRegister(); | |
@Override | |
public DemoOrderEntity draft(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能保存"); | |
} | |
@Override | |
public DemoOrderEntity submit(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能提交"); | |
} | |
@Override | |
public DemoOrderEntity approve(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能审核"); | |
} | |
@Override | |
public DemoOrderEntity unApprove(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能弃审"); | |
} | |
@Override | |
public DemoOrderEntity revoke(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能撤销"); | |
} | |
@Override | |
public DemoOrderEntity cancel(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能作废"); | |
} | |
@Override | |
public void remove(DemoOrderEntity demoOrderEntity) { | |
throw new ValidationException(demoOrderEntity.getStatus().getName() + "状态下,不能删除单据"); | |
} | |
} |
DemoOrderStateManage
package com.example.demo.helper; | |
import javax.validation.ValidationException; | |
import java.util.Map; | |
import java.util.concurrent.ConcurrentHashMap; | |
/** | |
* 单据状态管理器 | |
*/ | |
public class DemoOrderStateManage { | |
private Map<String,DemoOrderState> map = new ConcurrentHashMap<>(); | |
private DemoOrderStateManage(){} | |
/** | |
* 获取状态机 | |
* | |
* @param status 状态 | |
* @return 状态机 | |
*/ | |
public DemoOrderState getState(String status){ | |
DemoOrderState state = map.get(status); | |
if (state == null){ | |
throw new ValidationException("未找到对应的单据状态"); | |
} | |
return state; | |
} | |
/** | |
* 注册状态机 | |
* | |
* @param status 状态 | |
* @param state 状态机 | |
*/ | |
public void register(String status, DemoOrderState state){ | |
map.put(status, state); | |
} | |
public static DemoOrderStateManage getInstance(){return DemoOrderStateManageHolder.demoOrderStateManage;} | |
public static class DemoOrderStateManageHolder{ | |
public static DemoOrderStateManage demoOrderStateManage = new DemoOrderStateManage(); | |
} | |
} |
# 草稿
package com.example.demo.helper; | |
import com.example.demo.constant.Status; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.springframework.stereotype.Component; | |
/** | |
* 草稿单据可以保存、提交和删除单据操作 | |
* 所以只需实现对应的方法,未实现的方式不能操作 | |
*/ | |
@Component | |
public class DemoOrderDraft extends AbstractDemoOrderState{ | |
@Override | |
protected String getStatusForRegister() { | |
return Status.DRAFT.getCode(); | |
} | |
@Override | |
public DemoOrderEntity draft(DemoOrderEntity demoOrderEntity) { | |
// 草稿状态 -> 保存之后 -> 还是草稿状态 | |
demoOrderEntity.setStatus(Status.DRAFT.toType()); | |
return demoOrderDao.add(demoOrderEntity); | |
} | |
@Override | |
public DemoOrderEntity submit(DemoOrderEntity demoOrderEntity) { | |
// 草稿状态 -> 提交之后 -> 待审核状态 | |
demoOrderEntity.setStatus(Status.WAIT.toType()); | |
return demoOrderEntity; | |
} | |
@Override | |
public void remove(DemoOrderEntity demoOrderEntity) { | |
// 草稿状态的单据可删除 | |
demoOrderDao.remove(demoOrderEntity); | |
} | |
} |
# 待审核
package com.example.demo.helper; | |
import com.example.demo.constant.Status; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.springframework.stereotype.Component; | |
/** | |
* 待审核状态可进行审核、撤销和作废操作 | |
*/ | |
@Component | |
public class DemoOrderWait extends AbstractDemoOrderState{ | |
@Override | |
protected String getStatusForRegister() { | |
return Status.WAIT.getCode(); | |
} | |
@Override | |
public DemoOrderEntity approve(DemoOrderEntity demoOrderEntity) { | |
// 待审核状态 -> 审核之后 -> 已审核 | |
demoOrderEntity.setStatus(Status.COMPLETE.toType()); | |
return demoOrderEntity; | |
} | |
@Override | |
public DemoOrderEntity revoke(DemoOrderEntity demoOrderEntity) { | |
// 待审核状态 -> 撤销 -> 草稿状态 | |
demoOrderEntity.setStatus(Status.DRAFT.toType()); | |
return demoOrderEntity; | |
} | |
@Override | |
public DemoOrderEntity cancel(DemoOrderEntity demoOrderEntity) { | |
// 待审核状态 -> 作废 -> 已作废状态(之后只可执行删除操作了) | |
demoOrderEntity.setStatus(Status.CANCEL.toType()); | |
return demoOrderEntity; | |
} | |
} |
# 已审核
package com.example.demo.helper; | |
import com.example.demo.constant.Status; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.springframework.stereotype.Component; | |
/** | |
* 已审核状态,可进行弃审操作。 | |
*/ | |
@Component | |
public class DemoOrderStateComplete extends AbstractDemoOrderState{ | |
@Override | |
protected String getStatusForRegister() { | |
return Status.COMPLETE.getCode(); | |
} | |
@Override | |
public DemoOrderEntity unApprove(DemoOrderEntity demoOrderEntity) { | |
// 已审核 -> 弃审 -> 草稿状态 | |
demoOrderEntity.setStatus(Status.DRAFT.toType()); | |
return demoOrderEntity; | |
} | |
} |
# 已作废
package com.example.demo.helper; | |
import com.example.demo.constant.Status; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.springframework.stereotype.Component; | |
/** | |
* 已作废状态,可进行删除操作 | |
*/ | |
@Component | |
public class DemoOrderStateCancel extends AbstractDemoOrderState{ | |
@Override | |
protected String getStatusForRegister() { | |
return Status.CANCEL.getCode(); | |
} | |
@Override | |
public void remove(DemoOrderEntity demoOrderEntity) { | |
// 已作废的状态只能做删除操作 | |
demoOrderDao.remove(demoOrderEntity); | |
} | |
} |
# 业务层
DemoOrderService
package com.example.demo.service; | |
import com.example.demo.entity.DemoOrderEntity; | |
public interface DemoOrderService { | |
DemoOrderEntity draft(DemoOrderEntity demoOrderEntity); | |
DemoOrderEntity submit(DemoOrderEntity demoOrderEntity); | |
DemoOrderEntity approve(DemoOrderEntity demoOrderEntity); | |
DemoOrderEntity unApprove(DemoOrderEntity demoOrderEntity); | |
DemoOrderEntity revoke(DemoOrderEntity demoOrderEntity); | |
DemoOrderEntity cancel(DemoOrderEntity demoOrderEntity); | |
void remove(DemoOrderEntity demoOrderEntity); | |
} |
DemoOrderServiceImpl
package com.example.demo.service; | |
import com.example.demo.entity.DemoOrderEntity; | |
import com.example.demo.helper.DemoOrderState; | |
import com.example.demo.helper.DemoOrderStateManage; | |
import org.springframework.stereotype.Service; | |
@Service | |
public class DemoOrderServiceImpl implements DemoOrderService{ | |
@Override | |
public DemoOrderEntity draft(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
return state.draft(demoOrderEntity); | |
} | |
@Override | |
public DemoOrderEntity submit(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
return state.submit(demoOrderEntity); | |
} | |
@Override | |
public DemoOrderEntity approve(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
return state.approve(demoOrderEntity); | |
} | |
@Override | |
public DemoOrderEntity unApprove(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
return state.unApprove(demoOrderEntity); | |
} | |
@Override | |
public DemoOrderEntity revoke(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
return state.revoke(demoOrderEntity); | |
} | |
@Override | |
public DemoOrderEntity cancel(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
return state.cancel(demoOrderEntity); | |
} | |
@Override | |
public void remove(DemoOrderEntity demoOrderEntity) { | |
DemoOrderState state = DemoOrderStateManage.getInstance().getState(demoOrderEntity.getStatus().getCode()); | |
state.remove(demoOrderEntity); | |
} | |
} |
# 测试
package com.example.demo.service; | |
import com.example.demo.MainApplication; | |
import com.example.demo.constant.Status; | |
import com.example.demo.entity.DemoOrderEntity; | |
import org.junit.jupiter.api.Test; | |
import org.junit.jupiter.api.extension.ExtendWith; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.context.SpringBootTest; | |
@SpringBootTest(classes = MainApplication.class) | |
class DemoOrderServiceImplTest { | |
@Autowired | |
private DemoOrderService demoOrderService; | |
@Autowired | |
private DemoOrderDao demoOrderDao; | |
@Test | |
void draft(){ | |
// 当前【草稿】状态,可以保存! | |
DemoOrderEntity demoOrderEntity = new DemoOrderEntity(); | |
demoOrderEntity.setCode("DEMO_001"); | |
demoOrderEntity.setStatus(Status.DRAFT.toType()); | |
demoOrderService.draft(demoOrderEntity); | |
} | |
@Test | |
void submit(){ | |
// 保存之后为【草稿】状态,可以提交! | |
draft(); | |
DemoOrderEntity order_draft = demoOrderDao.findByCode("DEMO_001"); | |
demoOrderService.submit(order_draft); | |
} | |
@Test | |
void remove(){ | |
// 提交之后为【待审核】状态,不能删除! | |
submit(); | |
DemoOrderEntity order_wait = demoOrderDao.findByCode("DEMO_001"); | |
demoOrderService.remove(demoOrderEntity); | |
} | |
@Test | |
void approve(){ | |
// 提交之后为【待审核】状态,可以审核! | |
submit(); | |
DemoOrderEntity order_wait = demoOrderDao.findByCode("DEMO_001"); | |
demoOrderEntity = demoOrderService.approve(demoOrderEntity); | |
} | |
@Test | |
void unApprove(){ | |
// 审核之后为【已审核】状态,可以弃审! | |
approve(); | |
DemoOrderEntity order_complete = demoOrderDao.findByCode("DEMO_001"); | |
demoOrderService.unApprove(order_complete); | |
} | |
@Test | |
void remove2(){ | |
// 审核之后为【已审核】状态,不能删除! | |
approve(); | |
DemoOrderEntity order_wait = demoOrderDao.findByCode("DEMO_001"); | |
demoOrderService.remove(demoOrderEntity); | |
} | |
} |