×
文章路径: Java

审核状态机-状态模式的应用

发表于2年前(Dec 14, 2016 8:54:35 PM)  阅读 3494  评论 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、总结

通过使用状态机,将每一个条件分支放到一个独立的类里面,使用钩子函数,代码更加规范,整洁。

发表评论