审核状态机-状态模式的应用
发表于4年前(Dec 14, 2016 8:54:35 PM)  阅读 4887  评论 2
分类: Java
1、前言
简单描述一下状态模式:
状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
这里笔者实现一个审核状态机,主要流程是,用户申请审核,审核人员进行审核通过或者拒绝操作,允许用户取消审核申请。这是常用的一个业务流程,用户可以根据实际情况修改。
2、状态
首先,找出所有的状态,如下图:
NullState主要是初始化的时候给的状态。PassEndState主要是为了应对后面的多层审核机制而加上的,因为管理比较严的流程经常需要进行多层审核。
3、方法
审核流程中的操作基本上归纳为:申请审核(apply),审核通过(pass),审核不通过(reject),审核取消(cancel)。
4、状态转换
状态转换如下图:
这里是笔者定义的状态可能的转换模式,实际使用时可能因业务有些许不同。
5、实现:
审核状态机,VerifyMachine:
/**
* 审核状态机
* @author cangzhitao
*
*/
public abstract class VerifyMachine {
protected VerifyState nullState;
protected VerifyState applyState;
protected VerifyState cancelState;
protected VerifyState passState;
protected VerifyState rejectState;
protected VerifyState passEndState;
protected VerifyState state;
public VerifyMachine() {
this(null);
}
public VerifyMachine(VerifyState state) {
applyState = new ApplyState(this);
cancelState = new CancelState(this);
passState = new PassState(this);
rejectState = new RejectState(this);
nullState = new NullState(this);
if(state==null) {
this.state = nullState;
} else {
this.state = state;
}
}
public VerifyState getApplyState() {
return applyState;
}
public VerifyState getCancelState() {
return cancelState;
}
public VerifyState getPassState() {
return passState;
}
public VerifyState getRejectState() {
return rejectState;
}
public VerifyState getPassEndState() {
return passEndState;
}
public VerifyState getNullState() {
return nullState;
}
public void setState(VerifyState verifyState) {
state = verifyState;
}
public VerifyState getState() {
return state;
}
/**
* 申请审核
*/
public abstract boolean apply();
/**
* 审核通过
*/
public abstract boolean pass();
/**
* 审核不通过
*/
public abstract boolean reject();
/**
* 撤销审核
*/
public abstract boolean cancel();
}
审核状态的基类,VerifyState:
/**
* 审核状态的基类
* @author cangzhitao
*
*/
public abstract class VerifyState {
protected VerifyMachine verifyMachine;
public VerifyState(VerifyMachine verifyMachine) {
this.verifyMachine = verifyMachine;
}
/**
* 申请审核
*/
public abstract void apply() throws UnSupportStateTransferException;
/**
* 撤销审核
*/
public abstract void cancel() throws UnSupportStateTransferException;
/**
* 审核通过
*/
public abstract void pass() throws UnSupportStateTransferException;
/**
* 审核最终通过
*/
public abstract void passEnd() throws UnSupportStateTransferException;
/**
* 审核不通过
*/
public abstract void reject() throws UnSupportStateTransferException;
}
状态转换异常,UnSupportStateTransferException:
public class UnSupportStateTransferException extends Exception {
/**
*
*/
private static final long serialVersionUID = -8559085859581188939L;
public UnSupportStateTransferException() {
super();
}
public UnSupportStateTransferException(String message, Throwable cause) {
super(message, cause);
}
public UnSupportStateTransferException(String message) {
super(message);
}
public UnSupportStateTransferException(Throwable cause) {
super(cause);
}
}
空状态NullState:
/**
* 空审核状态
* @author cangzhitao
*
*/
public class NullState extends VerifyState {
public NullState(VerifyMachine verifyMachine) {
super(verifyMachine);
}
@Override
public void apply() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getApplyState());
}
@Override
public void pass() {
verifyMachine.setState(verifyMachine.getPassState());
}
@Override
public void reject() {
verifyMachine.setState(verifyMachine.getRejectState());
}
@Override
public void cancel() {
verifyMachine.setState(verifyMachine.getCancelState());
}
@Override
public void passEnd() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getPassEndState());
}
}
待审核状态ApplyState:
/**
* 待审核状态
* @author cangzhitao
*
*/
public class ApplyState extends VerifyState {
public ApplyState(VerifyMachine verifyMachine) {
super(verifyMachine);
}
@Override
public void apply() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从待审核状态转移到待审核状态!");
}
@Override
public void pass() {
verifyMachine.setState(verifyMachine.getPassState());
}
@Override
public void reject() {
verifyMachine.setState(verifyMachine.getRejectState());
}
@Override
public void cancel() {
verifyMachine.setState(verifyMachine.getCancelState());
}
@Override
public void passEnd() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getPassEndState());
}
}
审核通过状态PassState:
/**
* 审核通过状态
* @author cangzhitao
*
*/
public class PassState extends VerifyState {
public PassState(VerifyMachine verifyMachine) {
super(verifyMachine);
}
@Override
public void apply() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getApplyState());
}
@Override
public void cancel() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getCancelState());
}
@Override
public void pass() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核通过状态转移到审核通过状态!");
}
@Override
public void reject() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核状态转移到审核不通过状态!");
}
@Override
public void passEnd() throws UnSupportStateTransferException {
// throw new UnSupportStateTransferException("不支持从审核通过状态转移到审核最终通过状态!");
verifyMachine.setState(verifyMachine.getPassEndState());
}
}
审核不通过状态RejectState:
/**
* 审核不通过状态
* @author cangzhitao
*
*/
public class RejectState extends VerifyState {
public RejectState(VerifyMachine verifyMachine) {
super(verifyMachine);
}
@Override
public void apply() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getApplyState());
}
@Override
public void cancel() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getCancelState());
}
@Override
public void pass() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核不通过状态转移到审核通过状态!");
}
@Override
public void reject() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核不通过状态转移到审核不通过状态!");
}
@Override
public void passEnd() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核不通过状态转移到审核最终通过状态!");
}
}
审核取消状态CancelState:
/**
* 取消审核状态
* @author cangzhitao
*
*/
public class CancelState extends VerifyState {
public CancelState(VerifyMachine verifyMachine) {
super(verifyMachine);
}
@Override
public void apply() throws UnSupportStateTransferException {
verifyMachine.setState(verifyMachine.getApplyState());
}
@Override
public void cancel() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从撤销状态转移到撤销状态!");
}
@Override
public void pass() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从撤销状态转移到审核通过状态!");
}
@Override
public void reject() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从撤销状态转移到审核不通过状态!");
}
@Override
public void passEnd() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从撤销状态转移到审核最终通过状态!");
}
}
审核最终通过状态PassEndState:
/**
* 审核最终通过状态
* @author cangzhitao
*
*/
public class PassEndState extends VerifyState {
public PassEndState(VerifyMachine verifyMachine) {
super(verifyMachine);
}
@Override
public void apply() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核最终通过状态转移到其他状态!");
}
@Override
public void cancel() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核最终通过状态转移到其他状态!");
}
@Override
public void pass() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核最终通过状态转移到其他状态!");
}
@Override
public void reject() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核最终通过状态转移到其他状态!");
}
@Override
public void passEnd() throws UnSupportStateTransferException {
throw new UnSupportStateTransferException("不支持从审核最终通过状态转移到其他状态!");
}
}
多层审核状态机的一个实现,MultiLevelVerifyMachine:
/**
* 多层审核状态机
* 初始状态默认为NullState,理论上数据库里不存在这样的记录
* 通过apply进行审核申请,进入待审核状态.
* 理论上每层审核完都需要重新审核下一级审核,根据实际情况,该状态机在审核通过时直接做了申请下一层审核的操作,如果已没有下一级审核,则进入审核通过结束状态,将不能再进行其他操作.
* 使用时,一般继承该状态机,添加自己的业务数据.覆盖钩子函数,对每一步操作进行处理,如记审核日志,发布数据等.
* 建议使用MultiLevelVerifyMachine(int level, String verifyStatus)构造函数构造审核状态机的中间状态.
* 您可能先需要将之前的记录状态值转换成状态机所识别的verifyStatus状态标识才能使用.
* @author cangzhitao
*
*/
public class MultiLevelVerifyMachine extends VerifyMachine {
/**
* 需要审核的层数,默认为1
*/
private int endLevel = 1;
/**
* 已经审核通过的层数
*/
private int passLevel = 0;
public MultiLevelVerifyMachine() {
super();
}
public MultiLevelVerifyMachine(int level) {
super(null);
this.endLevel = level;
this.passLevel = 0;
}
public MultiLevelVerifyMachine(int level, VerifyState verifyState) {
super(verifyState);
this.endLevel = level;
this.passLevel = 0;
}
public MultiLevelVerifyMachine(VerifyState verifyState) {
this(1, verifyState);
}
public MultiLevelVerifyMachine(int level, String verifyStatus) {
super();
this.endLevel = level;
this.passLevel = 0;
if(verifyStatus==null||"".equals(verifyStatus)||"N".equals(verifyStatus)) {
this.setState(getNullState());
} else if(verifyStatus.startsWith("A")) {
this.setState(getApplyState());
this.setPassLevel(Integer.parseInt(verifyStatus.substring(1)));
} else if(verifyStatus.startsWith("P")) {
this.setState(getPassState());
this.setPassLevel(Integer.parseInt(verifyStatus.substring(1)));
} else if("C".equals(verifyStatus)) {
this.setState(getCancelState());
} else if("R".equals(verifyStatus)) {
this.setState(getRejectState());
} else if("E".equals(verifyStatus)) {
this.setState(getPassEndState());
}
}
/**
* 申请审核
*/
@Override
public boolean apply() {
if(this.isEnd()) {
return false;
}
try {
state.apply();
doAfterApply();
return true;
} catch (UnSupportStateTransferException e) {
e.printStackTrace();
}
return false;
}
/**
* 审核通过
*/
@Override
public boolean pass() {
if(this.isEnd()) {
return false;
}
try {
state.pass();
doAfterPass();
passLevel ++;
//检查是否已经到最后一层,如果是直接转到审核最终通过状态,否则自动转到申请审核状态
if(passLevel==endLevel) {
state.passEnd();
doAfterPassEnd();
} else {
//因为这里是自动执行的,所有没有再执行doAfterApply()方法
state.apply();
}
return true;
} catch (UnSupportStateTransferException e) {
e.printStackTrace();
}
return false;
}
/**
* 审核不通过
*/
@Override
public boolean reject() {
if(this.isEnd()) {
return false;
}
try {
state.reject();
doAfterReject();
passLevel = 0;
return true;
} catch (UnSupportStateTransferException e) {
e.printStackTrace();
}
return false;
}
/**
* 撤销审核
*/
@Override
public boolean cancel() {
if(this.isEnd()) {
return false;
}
try {
state.cancel();
doAfterCancel();
passLevel = 0;
return true;
} catch (UnSupportStateTransferException e) {
e.printStackTrace();
}
return false;
}
/**
* 判断流程是否结束
* @return
*/
public boolean isEnd() {
if(passLevel>=endLevel) {
return true;
}
return false;
}
/**
* 钩子函数,在申请审核后执行
*/
public void doAfterApply() {
}
/**
* 钩子函数,在审核通过后执行
*/
public void doAfterPass() {
}
/**
* 钩子函数,在审核不通过后执行
*/
public void doAfterReject() {
}
/**
* 钩子函数,在审核撤销后执行
*/
public void doAfterCancel() {
}
/**
* 钩子函数,在审核最终通过后执行
*/
public void doAfterPassEnd() {
}
public int getPassLevel() {
return passLevel;
}
public void setPassLevel(int passLevel) {
if(passLevel>this.endLevel) {
throw new RuntimeException("设置的已完成层级大于总共的层级!");
}
this.passLevel = passLevel;
}
public int getEndLevel() {
return endLevel;
}
/**
* 获取当前审核状态唯一标识符
* @return
*/
public String getVerifyStatus() {
if(this.getState() instanceof NullState) {
return "N";
} else if(this.getState() instanceof ApplyState) {
return "A"+passLevel;
} else if(this.getState() instanceof CancelState) {
return "C";
} else if(this.getState() instanceof PassState) {
return "P"+passLevel;
} else if(this.getState() instanceof RejectState) {
return "R";
} else if(this.getState() instanceof PassEndState) {
return "E";
}
return "N";
}
}
6、使用
实现一个用户注册的审核机,UserRegisterVerifyMachine:
public class UserRegisterVerifyMachine extends MultiLevelVerifyMachine {
public UserRegisterVerifyMachine() {
super(1);
}
@Override
public void doAfterApply() {
System.out.println("进行了申请审核操作!");
}
@Override
public void doAfterPass() {
System.out.println("进行了审核通过操作!");
}
@Override
public void doAfterReject() {
System.out.println("进行了审核不通过操作!");
}
@Override
public void doAfterCancel() {
System.out.println("进行了审核撤销操作!");
}
@Override
public void doAfterPassEnd() {
System.out.println("审核通过结束操作!");
}
}
这里我们简单的使用一层审核机制,使用方法:
public class TestUserRegisterVerifyMachine {
public static void main(String[] args) {
UserRegisterVerifyMachine machine = new UserRegisterVerifyMachine();
machine.apply();
machine.pass();
}
}
7、总结
通过使用状态机,将每一个条件分支放到一个独立的类里面,使用钩子函数,代码更加规范,整洁。