Loading...

本篇文章采用了状态模式实现了单据状态的相互变化(草稿、待审核、已审核、已撤销等等)。

单据(草稿)-> 提交操作 -> 单据(待审核)-> 审核操作 -> 单据(已审核)-> 弃审操作 -> 单据(草稿)

当单据处于【待审核】状态时,进行删除操作时,不是可行的,只可进行审核操作或者撤回操作。

# 引入依赖

<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);
    }
}
更新于

请我喝[茶]~( ̄▽ ̄)~*

七音 微信支付

微信支付

七音 支付宝

支付宝