在项目中经常会开发的功能,状态审批,在实际项目的开发中,发现很多人都是混合在业务代码中写死的方式去判断更新审核状态,后期维护会出现无法快速有效的整理每个状态前后节点之间的关系.跟业务代码耦合性太高,本篇以解耦和清晰的方式通过枚举方式实现一个简易易用的状态机
枚举代码块
- 所有的状态以及审核机制都维护在一个枚举类中,方便理解和维护
- 每一个枚举节点中维护了nextState()(通过状态)下一个节点,和rejectState()(拒绝状态)后返回上一个节点的关系维护
- currentStatus维护当前节点
- statusName维护当前节点名称
/**
* 状态机
*/
public enum StateEnum {
/**
* 未提交
*/
UnSubmitted {
@Override
public StateEnum nextState() {
//已提交 待生效
return Submitted_WaitActive;
}
@Override
public int currentStatus() {
return 0;
}
@Override
public String statusName() {
return "未提交";
}
@Override
public StateEnum rejectState() {
throw new Exception("状态异常");
}
},
/**
* 已提交 待生效
*/
Submitted_WaitActive {
@Override
public StateEnum nextState() {
return Submitted_TaskActive;
}
@Override
public int currentStatus() {
return 1;
}
@Override
public String statusName() {
return "待生效审批";
}
@Override
public StateEnum rejectState() {
return Submitted_Reject;
}
},
/**
* 已生效
*/
Submitted_TaskActive {
@Override
public StateEnum nextState() {
//作废
return Invalid_Wait;
}
@Override
public int currentStatus() {
return 2;
}
@Override
public String statusName() {
return "已生效";
}
@Override
public StateEnum rejectState() {
throw new Exception("状态异常");
}
},
/**
* 审批拒绝,未生效
*/
Submitted_Reject {
@Override
public StateEnum nextState() {
//未生效可重新审批到达待审批
return Submitted_WaitActive;
}
@Override
public int currentStatus() {
return 3;
}
@Override
public String statusName() {
return "未生效";
}
@Override
public StateEnum rejectState() {
return Submitted_Reject;
}
},
/**
* 待作废审批
*/
Invalid_Wait {
@Override
public StateEnum nextState() {
//未生效可重新审批到达已作废
return Invalid_TaskActive;
}
@Override
public int currentStatus() {
return 4;
}
@Override
public String statusName() {
return "待作废审批";
}
@Override
public StateEnum rejectState() {
return Invalid_Reject;
}
},
/**
* 已作废
*/
Invalid_TaskActive {
@Override
public StateEnum nextState() {
return Submitted_WaitActive;
}
@Override
public int currentStatus() {
return 5;
}
@Override
public String statusName() {
return "已作废";
}
@Override
public StateEnum rejectState() {
throw new Exception("状态异常");
}
},
/**
* 作废不通过
*/
Invalid_Reject {
@Override
public StateEnum nextState() {
//未生效可重新审批到达生效节点
return Invalid_Wait;
}
@Override
public int currentStatus() {
return 6;
}
@Override
public String statusName() {
return "作废不通过";
}
@Override
public StateEnum rejectState() {
return Invalid_Reject;
}
};
public static StateEnum get(int status){
for (StateEnum stateEnum : StateEnum.values()) {
if (stateEnum.currentStatus() == status) {
return stateEnum;
}
}
throw new Exception("无该状态");
}
//下一节点
public abstract StateEnum nextState();
//拒绝节点
public abstract StateEnum rejectState();
//当前状态
public abstract int currentStatus();
//状态名称
public abstract String statusName();
}
状态审核接口
实际业务中,只需要传递当前状态status和审核的动作statusType即可.
nextState对象得到审核后的状态信息,再根据实际业务走后续流程即可.
代码语言:javascript复制
static final int PASS = 1;
if (PASS == statusType) {
// 审批通过
nextState = StateEnum.get(status).nextState();
} else {
// 审批拒绝
nextState = StateEnum.get(status).rejectState();
}
/**
* 当前状态
*/
private int status;
/**
* 审核动作 1通过 2拒绝
*/
private int statusType;
封装通用装填审核接口
以上代码可以封装成一个接口,前端扭转状态时只需提供 1.业务ID 2.当前状态status 3.审核动作statusType
得到审核结果nextState后通过业务ID更新解耦业务,为了保证幂等性, 更新时需将前端传过来的当前状态也当做更新判断条件之一
代码语言:javascript复制
update table set status = nextState.currentStatus where 业务ID and status;