java-设计模式-状态模式-模拟审批流程-二级审批

设计模式的状态模式,就是把状态独立成一个类,代替传统复杂的if-else。

网上还有非常多关于状态模式的介绍,不过很多都是点到即止,例子我理解的也不是很清楚。设计模式只是一种思路,掌握好这个思路就可以,实现有非常多种方法。

接下来我有项目经典问题-审批流程,来使用下状态模式。

基本的审批流程如下: 提交表单 -> 一级审批 -> 二级审批 -> 结束

那对应的我也设置了四个状态: 提交表单状态、一级审批状态、二级审批状态、结束状态。

状态定义了三个动作: 同意并进入下一环节(agreeToNext)、驳回上一环节(backToBefore)、结束(finish)

接下来我先定义状态的父类,这里我用到了抽象类,而非接口,因为我想状态有很多通用属性。很多网上例子会把这些属性放到Context上下文里面,通过改变状态去修改这些属性,我觉得都可以。

此父类声明了很多状态的属性,以及定义了三个动作,但是我把结束动作方法给实现了,因为我觉得接收动作代码都是相同的。


/**
 * 提交状态0->一级审批1->二级审批2 ->审批完成3
 * 状态
 */
public abstract class Status {
    /**
     * 同意并进入下一环节
     * @param task 任务
     * @param msg 意见
     * @param nextUser 下一环节处理人
     */
    public abstract boolean agreeToNext(ApproveTask task, String msg, String nextUser);

    /**
     * 打回上一环节
     * @param task 任务
     * @param msg 意见
     * @return
     */
    public abstract boolean backToBefore(ApproveTask task, String msg);



    //属性
    String statusName;//状态名
    String user;//操作用户
    String suggest;//意见信息
    String request;//申请信息
    boolean operationFlag;//是否进行了操作
    int statusId = -1;
    boolean agreeFlag;//是否同意
    boolean isFinish;//是否终止状态
    int nextStatusId = -1;//下一环节 状态id


    /**
     * 构造方法
     */
    public Status(String user,String request) {
        this.user = user;
        this.request = request;
    }


    /**
     * 结束
     * @param task 任务
     * @param msg 意见
     */
    public boolean finish(ApproveTask task,String msg,boolean agreeFlag){
        System.out.println("环节结束 是否异常:"+agreeFlag);
        task.getApproveStatusList().add(this);//放入审批链中
        this.suggest = msg;
        this.agreeFlag = agreeFlag;
        this.nextStatusId = 3;
        this.operationFlag = true;
        //异常终止
        FinishStatus finishStatus = new FinishStatus(this.user,msg,agreeFlag);
        task.setStatus(finishStatus);
        task.getApproveStatusList().add(finishStatus);
        return true;
    }

    @Override
    public String toString() {
        return "状态名:"+statusName +" 状态id:"+statusId+" 下一环节id:"+
                nextStatusId+" 操作用户:"+user
                +" 是否进行了操作:"+operationFlag
                +" 是否同意:"+agreeFlag
                +" 申请信息:"+request
                +" 意见信息:"+ suggest;
    }


}

接下来是具体的状态类:

提交状态类


/**
 * 提交状态0->一级审批1->二级审批2 ->审批完成3
 *
 * 此类是提交状态
 *
 */
public class SubmitStatus extends Status{

    public SubmitStatus(String user,String request) {
        super(user,request);
        this.statusName = "提交状态";
        this.statusId = 0;
    }

    @Override
    public boolean agreeToNext(ApproveTask task,String msg,String nextUser){
        System.out.println("提交环节同意");
        this.operationFlag = true;
        this.agreeFlag = true;//
        this.suggest = msg;
        this.nextStatusId = statusId + 1;//下级状态
        task.getApproveStatusList().add(this);//放入审批路径
        task.setStatus(new FirstApproveStatus(nextUser,suggest));//设置下级审批,当前的意见成为下一审批人的申请信息
        return true;
    }

    @Override
    public boolean backToBefore(ApproveTask task,String msg){
        System.out.println("提交环节,不能打回");
        return false;
    }

}

一级审批状态类:


/**
 * 提交状态0->一级审批1->二级审批2 ->审批完成3
 * 一级审批
 */
public class FirstApproveStatus extends Status{

    /**
     * 构造方法
     *
     * @param user
     */
    public FirstApproveStatus(String user,String request) {
        super(user,request);
        this.statusName = "一级审批";
        this.statusId = 1;
    }

    @Override
    public boolean agreeToNext(ApproveTask task, String msg, String nextUser) {
        System.out.println("一级审批同意");
        this.agreeFlag = true;//
        this.operationFlag = true;
        this.suggest = msg;
        this.nextStatusId = statusId + 1;//下级状态
        task.getApproveStatusList().add(this);//放入审批路径
        task.setStatus(new SecondApproveStatus(nextUser,this.suggest));//设置下级审批
        return true;
    }

    @Override
    public boolean backToBefore(ApproveTask task, String msg) {
        System.out.println("一级审批回退");
        this.agreeFlag = false;
        this.operationFlag = true;
        this.suggest = msg;
        this.nextStatusId = statusId -1;
        String beforeUserId = task.getApproveStatusList().get(task.getApproveStatusList().size() - 1).user;
        task.getApproveStatusList().add(this);
        task.setStatus(new SubmitStatus(beforeUserId,this.suggest));
        return true;
    }

}

二级审批状态类:


public class SecondApproveStatus extends Status {
    /**
     * 构造方法
     *
     * @param user
     */
    public SecondApproveStatus(String user,String request) {
        super(user,request);
        this.statusName = "二级审批";
        this.statusId = 2;
    }

    @Override
    public boolean agreeToNext(ApproveTask task, String msg, String nextUser) {
        System.out.println("二级审批同意");
       /* this.agreeFlag = true;//
        this.suggest = msg;
        this.nextStatusId = statusId + 1;//下级状态
        task.getApproveStatusList().add(this);//放入审批路径
        Status finishStatus = new FinishStatus(this.user,this.suggest,true);
        task.setStatus(finishStatus);//设置下级审批
        task.getApproveStatusList().add(finishStatus);//放入审批路径
        */
       this.finish(task,msg,true);
        return true;
    }

    @Override
    public boolean backToBefore(ApproveTask task, String msg) {
        System.out.println("二级审批回退");
        this.agreeFlag = false;
        this.suggest = msg;
        this.nextStatusId = statusId -1;
        this.operationFlag = true;
        String beforeUserId = task.getApproveStatusList().get(task.getApproveStatusList().size() - 1).user;
        task.getApproveStatusList().add(this);
        task.setStatus(new FirstApproveStatus(beforeUserId,this.suggest));
        return true;
    }


}

结束状态类:


/**
 * 提交状态0->一级审批1->二级审批2 ->审批完成3
 * 一级审批
 */
public class FirstApproveStatus extends Status{

    /**
     * 构造方法
     *
     * @param user
     */
    public FirstApproveStatus(String user,String request) {
        super(user,request);
        this.statusName = "一级审批";
        this.statusId = 1;
    }

    @Override
    public boolean agreeToNext(ApproveTask task, String msg, String nextUser) {
        System.out.println("一级审批同意");
        this.agreeFlag = true;//
        this.operationFlag = true;
        this.suggest = msg;
        this.nextStatusId = statusId + 1;//下级状态
        task.getApproveStatusList().add(this);//放入审批路径
        task.setStatus(new SecondApproveStatus(nextUser,this.suggest));//设置下级审批
        return true;
    }

    @Override
    public boolean backToBefore(ApproveTask task, String msg) {
        System.out.println("一级审批回退");
        this.agreeFlag = false;
        this.operationFlag = true;
        this.suggest = msg;
        this.nextStatusId = statusId -1;
        String beforeUserId = task.getApproveStatusList().get(task.getApproveStatusList().size() - 1).user;
        task.getApproveStatusList().add(this);
        task.setStatus(new SubmitStatus(beforeUserId,this.suggest));
        return true;
    }

}

接下来是任务类,也就是很多网络例子的Context上下文 或环境。

这个类有当前的状态、还有整个审批状态流的属性,还有提供对外的 同意、驳回、拒绝等操作,外部只需要对此类进行操作即可


import java.util.ArrayList;
import java.util.List;

/**
 * 审批任务 相当于 状态模式的Context 环境
 *
 */
public class ApproveTask {
    private Status status;//当前的状态
    private List<Status> approveStatusList = new ArrayList<>();//审批操作人 此处可以扩展

    /**
     * 任务 构造函数
     */
    public ApproveTask(String user){
        this.status = new SubmitStatus(user,null);
    }
    /**
     * 同意 要写同意意见
     * @param msg 同意意见
     */
    public void agree(String msg,String nextUser){
        status.agreeToNext(this,msg,nextUser);
    }

    /**
     * 驳回
     * @param msg
     */
    public void back(String msg){
        status.backToBefore(this,msg);
    }

    public void refuse(String msg){
        status.finish(this,msg,false);
    }

    /**
     * 打印审批路径
     */
    public void showApprovePath(){
        approveStatusList.stream().forEach(System.out::println);
    }
    //getter and setter


    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public List<Status> getApproveStatusList() {
        return approveStatusList;
    }

    public void setApproveStatusList(List<Status> approveStatusList) {
        this.approveStatusList = approveStatusList;
    }
}

测试方法1(正常二级审批流程):

 public static void normal(){
        System.out.println("---------正常流程----------");
        ApproveTask approveTask = new ApproveTask("小红");//小红新建个审批任务
        approveTask.agree("由于工作需要,申请对工程机进行使用 3天","小明");//小红写申请书,提交给 小明
        approveTask.agree("小红需要对工程师进行使用,初步决定可以","小亮");//小明一级审批同意,并发送给小亮
        approveTask.agree("情况属实,可以批准",null);//小亮审批同意

        System.out.println();
        System.out.println("----整体审批路径如下----");
        approveTask.showApprovePath();
    }

运行结果:

---------正常流程----------
提交环节同意
一级审批同意
二级审批同意
环节结束 是否异常:true

----整体审批路径如下----
状态名:提交状态 状态id:0 下一环节id:1 操作用户:小红 是否进行了操作:true 是否同意:true 申请信息:null 意见信息:由于工作需要,申请对工程机进行使用 3天
状态名:一级审批 状态id:1 下一环节id:2 操作用户:小明 是否进行了操作:true 是否同意:true 申请信息:由于工作需要,申请对工程机进行使用 3天 意见信息:小红需要对工程师进行使用,初步决定可以
状态名:二级审批 状态id:2 下一环节id:3 操作用户:小亮 是否进行了操作:true 是否同意:true 申请信息:小红需要对工程师进行使用,初步决定可以 意见信息:情况属实,可以批准
状态名:结束环境 状态id:-1 下一环节id:-1 操作用户:小亮 是否进行了操作:true 是否同意:true 申请信息:情况属实,可以批准 意见信息:null

测试方法2(驳回例子):

public static void back(){
        System.out.println("---------驳回流程--------");
        System.out.println("新建任务");
        ApproveTask approveTask = new ApproveTask("小红");//小红新建个审批任务
        System.out.println("现在的任务状态:"+approveTask.getStatus());
        approveTask.agree("由于工作需要,申请对工程机进行使用 3天","小明");//小红写申请书,提交给 小明
        System.out.println("现在的任务状态:"+approveTask.getStatus());
        approveTask.agree("小红需要对工程师进行使用,初步决定可以","小亮");//小明一级审批同意,并发送给小亮
        System.out.println("现在的任务状态:"+approveTask.getStatus());
        approveTask.back("不行呀,请再检查检查");//小亮 二级审批不同意
        System.out.println("现在的任务状态:"+approveTask.getStatus());
        approveTask.agree("已经检查过库存了,确定可以","小亮");//小明一级审批再次同意
        System.out.println("现在的任务状态:"+approveTask.getStatus());
        approveTask.agree("情况属实,可以批准",null);//小亮审批同意

        System.out.println();
        System.out.println("----整体审批路径如下----");
        approveTask.showApprovePath();
    }

运行结果:

---------驳回流程--------
新建任务
现在的任务状态:状态名:提交状态 状态id:0 下一环节id:-1 操作用户:小红 是否进行了操作:false 是否同意:false 申请信息:null 意见信息:null
提交环节同意
现在的任务状态:状态名:一级审批 状态id:1 下一环节id:-1 操作用户:小明 是否进行了操作:false 是否同意:false 申请信息:由于工作需要,申请对工程机进行使用 3天 意见信息:null
一级审批同意
现在的任务状态:状态名:二级审批 状态id:2 下一环节id:-1 操作用户:小亮 是否进行了操作:false 是否同意:false 申请信息:小红需要对工程师进行使用,初步决定可以 意见信息:null
二级审批回退
现在的任务状态:状态名:一级审批 状态id:1 下一环节id:-1 操作用户:小明 是否进行了操作:false 是否同意:false 申请信息:不行呀,请再检查检查 意见信息:null
一级审批同意
现在的任务状态:状态名:二级审批 状态id:2 下一环节id:-1 操作用户:小亮 是否进行了操作:false 是否同意:false 申请信息:已经检查过库存了,确定可以 意见信息:null
二级审批同意
环节结束 是否异常:true

----整体审批路径如下----
状态名:提交状态 状态id:0 下一环节id:1 操作用户:小红 是否进行了操作:true 是否同意:true 申请信息:null 意见信息:由于工作需要,申请对工程机进行使用 3天
状态名:一级审批 状态id:1 下一环节id:2 操作用户:小明 是否进行了操作:true 是否同意:true 申请信息:由于工作需要,申请对工程机进行使用 3天 意见信息:小红需要对工程师进行使用,初步决定可以
状态名:二级审批 状态id:2 下一环节id:1 操作用户:小亮 是否进行了操作:true 是否同意:false 申请信息:小红需要对工程师进行使用,初步决定可以 意见信息:不行呀,请再检查检查
状态名:一级审批 状态id:1 下一环节id:2 操作用户:小明 是否进行了操作:true 是否同意:true 申请信息:不行呀,请再检查检查 意见信息:已经检查过库存了,确定可以
状态名:二级审批 状态id:2 下一环节id:3 操作用户:小亮 是否进行了操作:true 是否同意:true 申请信息:已经检查过库存了,确定可以 意见信息:情况属实,可以批准
状态名:结束环境 状态id:-1 下一环节id:-1 操作用户:小亮 是否进行了操作:true 是否同意:true 申请信息:情况属实,可以批准 意见信息:null

小结:

以上就是状态模式模拟审批流程的简单例子。

当然,有很多优化的地方,比如 驳回可以选择驳回环节、任务类需要可以进行序列化和反序列化,可以把任务结果保存入数据库中,并且可以根据数据库中存入的值还原成任务类等操作。

发布了60 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/xiaoluo5238/article/details/104592927