EventBus-实现java状态机

摘自:https://www.jianshu.com/p/8def04b34b3cjava

首先,了解状态机是什么,咱们为何须要状态机!
举个最简单例子,请假,做为一个最底层程序员,每次请假都要领导层层审批,而假有分为不少种,事假,病假,婚假,年休假等等,固然选择请的假不一样,审批标准也不一样,不一样的假单须要走的审批链也不同,好比年休假,可能只须要领导审批扣掉年休假便可,请病假须要领导审批,领导审批以后,先休假,等休完假回来提交病假的材料,由hr审批以后才能完成整个请假过程。更有甚者,若是你要修一个一个月的长假,就不只仅是须要直线领导hr审批,可能还须要公司ceo审批 ,审批经过后,才能经过。以下图:git


固然,实际来说,请假的种类和链路比这个要复杂的多,咱们通常会怎么实现,是否要使用if else了,对应不一样的假单,走不一样的分支,代码写出来就成了一个很是复杂的,多级嵌套的代码了,后面如何维护代码,多了几种假的种类,是否是又要if else了。以下代码:
 public void requestLeavePermit(String type){
        if(type.equals("事假")){
            //领导审批->hr审批->ceo审批->完成
        }else if(type.equals("病假")){
              //领导审批->休假->补充病例->hr审批->完成
        }else if(type.equals("年休假")){
               //领导审批->hr审批->经过
        }else if(type.equals("产假")){
            //领导审批->hr审批->经过
        }else if(type.equals("调休假")){
              //领导审批->ceo审批->经过
        }
    }

  或者写成这个样子:程序员

public void requestLeavePermit(String type,String userName){
        switch (type){
            case "事假":
                       //领导审批->hr审批->ceo审批->完成
                    break;
            case "病假":
                        //领导审批->休假->补充病例->hr审批->完成
                    break;
            case "年休假":
                        //领导审批->hr审批->经过
                    break;
            case "产假":
                      //领导审批->hr审批->经过
                    break;
            case "调休假":
                    //领导审批->ceo审批->经过
            default:
                    break;
        }
    }

  

if,else嵌套太深,而后每一个if,else又是本身的处理流程,这样代码结构会原来越复杂,当审批链发生变动,这个时候会发现代码耦合性太强,致使修改起来很麻烦。
如何解决这个问题,咱们不难看到,全部的请假都通过了这样几个阶段,从请假开始,提交假单,而后领导审批,hr审批,ceo审批,只是不一样的是,有些审批流程多了审核人或者是少了审核人,每种假单审核材料有所不一样而已。
咱们如何使用状态机来如何解决代码耦合性的问题,提升代码可扩展性可读性
若是咱们把领导审批,hr审批,ceo审批,分别看作一个动做,每一个相应都有几个状态,审批经过,不经过,拒绝,从新审核,会怎么样?

首先,咱们将请假的类型定义成一个枚举:
public enum LeavePermitEnum {

    ANNUAL_LEAVE("annual_leave","年休假 "),
    CASUAL_LEAVE("casual_leave","事假"),
    MEDICAL_LEAVE("medical_leave","病假"),
    MARRIAGE_LEAVE("marriage_leave","婚假"),;

    private String type;
    private String memo;
    //此处忽略构造方法和set/get方法
}

领导审批,hr审批,ceo审批,都有一个审批意见(经过,拒绝,或者是重修修改假单补充材料等),在这里,至关于一个事件Event,因而,整个状态扭转也能够用一个枚举类来表示,审批意见由一个枚举类Event来表示。github

public enum Event {

    AGREE("agree","赞成"),
    DISSAGREE("disagree","不一样意"),
    MODIFY("modify","修改"),
    ;
    private String type;
    private String memo;
}

  所以,一个假单的状态就有不少种,用一个枚举表明整个假单的状态:ide

public enum Status {
    //提交假单
    PERMIT_SUBMIT("permitSubmit","提交假单"),
     //领导审批
    LEADER_PERMITING("leaderPermiting","领导审批中"),
    LEADER_PERMIT_AGREE("leaderAgree","领导赞成"),
    LEADER_PERMIT_DISAGREE("leaderDisAgree","领导不一样意"),
    LEADER_PERMIT_MODIFY("leaderModify","领导以为须要补充材料重修修改"),

    //hr审批
    HR_PERMITING("hrPermiting","hr审批中"),
    HR_PERMIT_AGREE("hrAgree","hr赞成"),
    HR_PERMIT_DISAGREE("hrDisAgree","hr不一样意"),
    HR_PERMIT_MODIFY("hrModify","hr以为须要补充材料重修修改"),
    //ceo审批
    CEO_PERMITING("ceoPermiting","领导审批中"),
    CEO_PERMIT_AGREE("ceoAgree","ceo赞成"),
    CEO_PERMIT_DISAGREE("ceoDisAgree","ceo不一样意"),
    CEO_PERMIT_MODIFY("ceoModify","ceo以为须要补充材料重修修改"),

    //最终请假状态
    PERMIT_SUCCESS("permitSuccess","请假成功"),
    PERMIT_FAIL("permitFail","请假失败")
    ;

    private String status;
    private String memo;

    private Status(String status,String memo){
        this.status=status;
        this.memo=memo;
    }
}

  

状态定义清楚以后,须要考虑两个问题post

  • 从当前状态须要可以跳转到下一个状态,好比提交假单以后,要可以从提交假单状态跳转到领导审批状态。
  • 不一样的审批意见要可以跳转不一样的状态,好比领导审批状态跳转审批经过,或者拒绝该审批须要可以按照Event状态跳转不一样的状态。

这块功能能够交给状态机StatusMachine去解决,由当前状态+事件驱动(也就是当前请假的状态和审批意见)获取下一个状态。ui

咱们知道,请假的种类不一样,所走的流程也不一样,相应的处理也不一样,每种假单都有本身的审批链,也对应每种假单有不一样的状态机,不难设计StatusMachine为接口或抽象类。状态机只作一件事情,根据event(审批意见),跳转下一个状态机。this

public interface StatusMachine {
      /**
          *@params status 当前状态
          *@params event 审批意见
          *@return 下一个状态
       **/
     public Status getNextStatus(Status status,Event event);
}

  

这里举两个例子,一个病假,一个年休假的实现:设计

年休假的审批流程:code

  • 提交假单 PERMIT_SUBMIT
  • 领导审批 LEADER_PERMITING
  • 等待领导审批
  • 领导审批经过/不经过/拒绝
  • 领导审批经过 LEADER_PERMIT_AGREE
  • ceo审批 CEO_PERMITING
  • 等待ceo审批意见
  • ceo审批经过/不经过/拒绝
  • ceo审批经过 CEO_PERMIT_AGREE
  • 请假完成 PERMIT_SUCCESS

所以事假的状态机StatusMachine实现以下:



public class AnnualLeaveStatusMachine implements StatusMachine{


    public Status getNextStatus(Status status,Event event){
        switch (status){

            case PERMIT_SUBMIT:
                //提交假单状态无需审批跳转领导审批中状态
                return Status.LEADER_PERMITING;

            case LEADER_PERMITING:
                //领导审批须要审批意见 审批意见不用返回不一样的状态
                return getLeaderPermitStatus(event);
            case LEADER_PERMIT_AGREE:
                //领导赞成请假,则跳转ceo审批
                return Status.CEO_PERMITING;
            case LEADER_PERMIT_DISAGREE:
                //领导不一样意该假单,则请假失败
                return Status.PERMIT_FAIL;
            case LEADER_PERMIT_MODIFY:
                return getLeaderPermitStatus(event);

            case CEO_PERMITING:
                //ceo审批须要审批意见
                return getCEOPermitStatus(event);
            case CEO_PERMIT_AGREE:
                // ceo审批赞成 跳转审批经过 请假完成
                return Status.PERMIT_SUCCESS;
            
            case CEO_PERMIT_DISAGREE:
                //ceo不一样意审批 则跳转审批失败
                return Status.PERMIT_FAIL;
            case CEO_PERMIT_MODIFY:
                return  getCEOPermitStatus(event);

            default:
                throw new RuntimeException("没有该流程");
        }
    }



    private Status getLeaderPermitStatus(Event event){
        switch (event){
            case AGREE:
                //领导审批经过 返回赞成该假单
                return Status.LEADER_PERMIT_AGREE;
            case DISSAGREE:
                //领导不一样意 则返回领导拒绝改假单状态
                return Status.LEADER_PERMIT_DISAGREE;
            case MODIFY:
                return Status.LEADER_PERMIT_MODIFY;
            default:
                throw new RuntimeException("不支持该Event审批意见");
        }
    }


    private Status getCEOPermitStatus(Event event){
        switch (event){
            case AGREE:
                //ceo审批经过 则返回ceo赞成该假单
                return Status.CEO_PERMIT_AGREE;
            case DISSAGREE:
                // ceo审批不经过 则返回ceo不一样意该假单状态
                return Status.CEO_PERMIT_DISAGREE;
            case MODIFY:
                return Status.CEO_PERMIT_MODIFY;
            default:
                throw new RuntimeException("不支持该Event审批意见");
        }
    }
}

  

病假的审批流程:

  • 提交假单 PERMIT_SUBMIT
  • 领导审批 LEADER_PERMITING
  • 等待领导审批
  • 领导审批经过/不经过/拒绝
  • 领导审批经过 LEADER_PERMIT_AGREE
  • HR审批 HR_PERMITING
  • 等待HR审批意见
  • HR审批经过/不经过/拒绝
  • HR审批经过 CEO_PERMIT_AGREE
  • 请假完成 PERMIT_SUCCESS
    根据该流程不难设计出该状态机


public class MedicalLeaveStatusMachine implements StatusMachine{

    public Status getNextStatus(Status status,Event event){
        switch (status){
            case PERMIT_SUBMIT:
                    //提交假单状态直接跳转领导审批中状态
                    return Status.LEADER_PERMITING;


            case LEADER_PERMITING:
                    //领导审批中状态须要审批意见再获取下一个状态
                    return getLeaderPermitStatus(event);
            case LEADER_PERMIT_AGREE:
                    //领导赞成审批该假单 跳转hr审批中状态
                    return Status.HR_PERMITING; 
            case LEADER_PERMIT_DISAGREE:
                    //领导不一样意则返回请假失败
                    return Status.PERMIT_FAIL;
            case LEADER_PERMIT_MODIFY:
                    return  getLeaderPermitStatus(event);

            case HR_PERMITING:
                //hr审批根据审批意见跳转下一个状态
                return getHrPermitStatus(event);
            case HR_PERMIT_AGREE:
                //hr审批经过跳转审批完成状态
                return Status.PERMIT_SUCCESS;
            case HR_PERMIT_DISAGREE:
                // hr审批不一样意 返回请假失败
                return Status.PERMIT_FAIL;
            case HR_PERMIT_MODIFY:
                return  getHrPermitStatus(event);

            default:
                throw new RuntimeException("没有该流程");
        }
    }
    private Status getLeaderPermitStatus(Event event){
        switch (event){
            case AGREE:
                //领导赞成该假单,则返回领导审批经过
                return Status.LEADER_PERMIT_AGREE;
            case DISSAGREE:
                //领导不一样意该假单 则返回领导审批不经过
                return Status.LEADER_PERMIT_DISAGREE;
            case MODIFY:
                return Status.LEADER_PERMIT_MODIFY;
            default:
                throw new RuntimeException("不支持该Event审批意见");
        }
    }
    private Status getHrPermitStatus(Event event){
        switch (event){
            case AGREE:
                //hr审批赞成该假单,则返回hr赞成状态
                return Status.HR_PERMIT_AGREE;
            case DISSAGREE:
                //hr审批不一样意该假单,则返回hr不一样意状态
                return Status.HR_PERMIT_DISAGREE;
            case MODIFY:
                return Status.HR_PERMIT_MODIFY;
            default:
                throw new RuntimeException("不支持该Event审批意见");
        }
    }
}

  对于请假的员工来说,只知道提交了一个假单,并不会关心到底该流程怎么走,因此在设计的时候,须要根据请假类型可以自动匹配状态机,这里能够用静态工厂去实现。

public class StatusMachineFactory {

    private StatusMachineFactory(){

    }

    /**
     * 根据状态获取状态机
     * @param leavePermitType
     * @return 对应请假类型的状态机
     */
    public static StatusMachine getStatusMachine(LeavePermitType leavePermitType){
        switch (leavePermitType){
            case MEDICAL_LEAVE:
                return new MedicalLeaveStatusMachine();
            case ANNUAL_LEAVE:
                return new AnnualLeaveStatusMachine();
            default:
                throw new RuntimeException("未知类型");
        }
    }
}

  

状态机设计好以后,每一个状态都应该对应有该状态的处理类,且须要统一管理该状态和处理类的关系。
以年休假为例:提交假单->领导审批4个状态->ceo审批4个状态->请假完成/失败2个状态。

总计须要11个状态处理对象去处理该状态。

该状态处理类须要具有哪些能力

  • 处理该状态的业务
  • 可以决定要不要扭转该状态机接着往下走(提交假单状态处理结束要可以自动运行到领导审批状态,领导审批状态不能接着扭转到下一个状态,须要等待领导的审批意见才可继续往下走)

不难设计,先抽象出一个StatusHandler接口或父类,每一个状态的处理类去实现该接口或继承该父类,在statusHandler中,有三个方法,before,dohandler,after,after主要负责扭转状态机,获取下一个状态的处理类处理下一个状态的事件。若是状态到达某一个状态不须要往下继续执行,则重写after方法便可中断状态机,dohandler主要负责作业务处理。

 
       
public interface AbstractStatusHandler {
    public void handle(LeavePermit leavePermit);
}

public abstract class StatusHandler implements AbstractStatusHandler{

    protected void before(LeavePermit leavePermit){
    }


    public void handle(LeavePermit leavePermit){
        before(leavePermit);
        doHandler(leavePermit);
        after(leavePermit);
    }
    protected abstract void doHandler(LeavePermit leavePermit);

    protected void after(LeavePermit leavePermit){
        //去下一个状态的处理对象处理
        goNextStatusHandler(leavePermit);
    }

    protected void goNextStatusHandler(LeavePermit leavePermit){
        //获取下一个状态
        leavePermit.setStatus(StatusMachineFactory.getStatusMachine(leavePermit.getLeavePermitType()).getNextStatus(leavePermit.getStatus(),leavePermit.getEvent()));
        //状态机引擎驱动假单处理
        StatusMachineEngine.post(leavePermit);
    }

  在看一下具体的状态处理类实现,11个状态对应11个处理类,这里列举出部分

public class AnnualPermitSubmitStatusHandler extends StatusHandler{

    protected void doHandler(LeavePermit leavePermit){
        System.out.println(String.format("user:%s--提交年休假假单--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
    }

}

public class AnnualLeaderPermitingStatusHandler extends StatusHandler{

    protected void doHandler(LeavePermit leavePermit){
        System.out.println(String.format("user:%s--领导审批年休假中--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
    }
    @Override
    protected void after(LeavePermit leavePermit){
        if(leavePermit.getEvent()==null){
            //还未审批,状态机结束,等待审批意见
            System.out.println(String.format("user:%s--等待领导审批--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
            return;
        }
       super.goNextStatusHandler(leavePermit);
    }
}

public class AnnualLeaderAgreeStatusHandler extends StatusHandler{

    protected void doHandler(LeavePermit leavePermit){
        System.out.println(String.format("user:%s--直线领导赞成请年休假--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
    }

}
public class AnnualLeaderAgreeStatusHandler extends StatusHandler{

    protected void doHandler(LeavePermit leavePermit){
        leavePermit.setEvent(null);
        System.out.println(String.format("user:%s--直线领导赞成请年休假--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
    }

}

public class AnnualCEOPermitingStatusHandler extends StatusHandler{
    

    protected void doHandler(LeavePermit leavePermit){
        System.out.println(String.format("user:%s--ceo审批年休假中--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));

    }

    protected void after(LeavePermit leavePermit){
       if(leavePermit.getEvent()==null){
           //还未审批,状态机结束,等待审批意见
           System.out.println(String.format("user:%s--等待ceo审批--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
           return;
       }
        goNextStatusHandler(leavePermit);
    }

}
public class AnnualCEOAgreeStatusHandler extends StatusHandler{

    protected void doHandler(LeavePermit leavePermit){
        System.out.println(String.format("user:%s--ceo赞成休年休假--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus()));
    }

}

public class AnnualPermitSuccessStatusHandler extends StatusHandler{

    @Override
    protected void doHandler(LeavePermit leavePermit){
        System.out.println(String.format("user:%s--请年休假假成功--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus(),leavePermit.getStatus().getMemo()));
    }
    @Override
    protected void after(LeavePermit leavePermit){
    }
}

  关于假单的请求,都会由StatusMachineEngine.post(LeavePermit)去处理,这里是如何作到按照请假类型,和状态找到对应的statusHandler的?
这里是使用eventbus去实现(基于消息订阅发布模式实现)

public class StatusMachineEngine {

    private static EventBus eventBus;
    static{
        eventBus = new EventBus();
    }

    /**
     * 发布一条假单
     * @param leavePermit
     */
    public static void post(LeavePermit leavePermit) {
        eventBus.post(leavePermit);
    }

    /**
     * 假单处理类
     * @param statusLeavePermitHandler
     */
    public static void addListener(LeavePermitHandler statusLeavePermitHandler) {
        eventBus.register(statusLeavePermitHandler);
    }
}

  全部假单的处理都会交给LeavePermitHandler去处理,这个对象里按照请假类型和请假状态作路由,选择不一样的statusHandler处理业务逻辑。

public class LeavePermitHandler {

    //处理假单 注解表明能够接受到StatusMachineEngine发布的假单
    @Subscribe
    @AllowConcurrentEvents
    public void handle(LeavePermit leavePermit){
        //获取到状态处理类,而后去处理 handler为StatusHandler的入口
        getStatusHandler(leavePermit).handle(leavePermit);
    }

    /**
     * 根据假单获取StatusHandler 状态处理对象
     * @param leavePermit
     * @return
     */
    public static StatusHandler getStatusHandler(LeavePermit leavePermit){
        return StatusHandlerRegistry.acquireStatusHandler(leavePermit.getLeavePermitType(),leavePermit.getStatus());
    }
}

  全部的状态处理类都会保存在StatusHandlerRegistry对象中,该对象负责注册全部有关请假类型,状态和状态处理类的关系,每次都根据请假类型和状态去获取StatusHandler。

public class StatusHandlerRegistry {

    private static Map<String,StatusHandler> statusHandlerMap;

    static {
        statusHandlerMap=new ConcurrentHashMap<String, StatusHandler>();
    }

    private StatusHandlerRegistry(){

    }

    private static String getKey(LeavePermitType leavePermitType,Status status){
        return String.format("%s@-@%s",leavePermitType.getType(),status.name());
    }

    /**
     * 注册状态处理类
     * @param leavePermitType  请假类型
     * @param status           请假状态
     * @param statusHandler    状态处理对象
     */
    public static void registryStatusHandler(LeavePermitType leavePermitType,Status status,StatusHandler statusHandler){
        statusHandlerMap.put(getKey(leavePermitType,status),statusHandler);
    }

    /**
     * 获取状态处理类
     * @param leavePermitType  请假类型
     * @param status            请假状态
     * @return StatusHandler         
     */
    public static StatusHandler acquireStatusHandler(LeavePermitType leavePermitType,Status status){
        return statusHandlerMap.get(getKey(leavePermitType,status));
    }
}

  

因此,在咱们项目启动中,将请假类型,请假状态和状态处理对象StatusHandler注册到StatusHandlerRegistry中,当LeavePermitHandler 处理类接收到StatusHandlerEngine.post()的假单的时候,能够根据请假类型和状态获取相应的处理类StatusHandler,作相应状态逻辑的处理,逻辑处理结束,是否继续状态机取决于statusHandler的after方法是否调用goNextStatusHandler(leavePermit);在调用goNextStatusHandler(leavePermit)的时候,会去状态机获取下一个状态,StatusHandlerEngine.post(leavePermit)将继续去获取处理类statusHandler,这个时候,应为leavePermit的状态已经发生变化,因此获取到的statusHandler已经发生变化。
看一下运行结果:


public static void main(String[] args) {
       //注册年休假的状态和对应状态的处理类StatusHandler。
        registryAnnualPermitStatusHandler();
        //注册病假的状态和对应状态的处理类StatusHandler。
        registryMedicalPermitStatusHandler();

        LeavePermitHandler leavePermitHandler=new LeavePermitHandler();
        //状态机引擎接受事件处理类
        StatusMachineEngine.addListener(leavePermitHandler);
        //生成假单
        LeavePermit leavePermit=new LeavePermit();
        leavePermit.setLeavePermitType(LeavePermitType.ANNUAL_LEAVE);
        leavePermit.setStatus(Status.PERMIT_SUBMIT);
        leavePermit.setUser("jettyrun");
        //假单交给引擎去执行
        StatusMachineEngine.post(leavePermit);
        System.out.println("----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走-------");
        leavePermit.setEvent(Event.AGREE);
        StatusMachineEngine.post(leavePermit);
        System.out.println("----- 分割线 表明假条须要ceo审批了,ceo给个经过意见,而后状态机接着走-------");
        leavePermit.setEvent(Event.AGREE);
        StatusMachineEngine.post(leavePermit);
        System.out.println("--->>>>>>>>>end<<<<<<<<-------");

}


 public static void registryAnnualPermitStatusHandler() {

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.PERMIT_SUBMIT, new AnnualPermitSubmitStatusHandler());

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMIT_AGREE, new AnnualLeaderAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMIT_DISAGREE, new AnnualLeaderDisAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMIT_MODIFY, new AnnualLeaderPermitModifyStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMITING, new AnnualLeaderPermitingStatusHandler());

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMIT_AGREE, new AnnualCEOAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMIT_DISAGREE, new AnnualCEODisAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMIT_MODIFY, new AnnualCEOPermitModifyStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMITING, new AnnualCEOPermitingStatusHandler());

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.PERMIT_SUCCESS, new AnnualPermitSuccessStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.PERMIT_FAIL, new AnnualPermitFailStatusHandler());
    }



    public static void registryMedicalPermitStatusHandler() {

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.PERMIT_SUBMIT, new MedicalPermitSubmitStatusHandler());

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMIT_AGREE, new MedicalLeaderAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMIT_DISAGREE, new MedicalLeaderDisAgreeStatusHandler
                ());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMIT_MODIFY, new MedicalLeaderPermitModifyStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMITING, new MedicalLeaderPermitingStatusHandler());

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMIT_AGREE, new MedicalHrAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMIT_DISAGREE, new MedicalHrDisAgreeStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMIT_MODIFY, new MedicalHrPermitModifyStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMITING, new MedicalHrPermitingStatusHandler());

        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.PERMIT_SUCCESS, new MedicalPermitSuccessStatusHandler());
        StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.PERMIT_FAIL, new MedicalPermitFailStatusHandler());
    }

  执行结果:

user:jettyrun--提交年休假假单--leavePermit status:permitSubmit
user:jettyrun--领导审批年休假中--leavePermit status:leaderPermiting
user:jettyrun--等待领导审批--leavePermit status:leaderPermiting
----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走-------
user:jettyrun--领导审批年休假中--leavePermit status:leaderPermiting
user:jettyrun--直线领导赞成请年休假--leavePermit status:leaderAgree
user:jettyrun--ceo审批年休假中--leavePermit status:ceoPermiting
user:jettyrun--等待ceo审批--leavePermit status:ceoPermiting
----- 分割线 表明假条须要领导审批了,ceo给个经过意见,而后状态机接着走-------
user:jettyrun--ceo审批年休假中--leavePermit status:ceoPermiting
user:jettyrun--ceo赞成休年休假--leavePermit status:ceoAgree
user:jettyrun--请年休假假成功--leavePermit status:permitSuccess
--->>>>>>>>>end<<<<<<<<-------


  

能够看到,当须要领导,CEO审批假单的时候,状态机可以自动中断,领导,ceo赞成了该请假请求leavePermit.setEvent(Event.AGREE);状态机就可以自动运行到最终状态permitSuccess。
这只是请年休假,再请一个病假
 LeavePermit leavePermit2=new LeavePermit();
        leavePermit2.setLeavePermitType(LeavePermitType.MEDICAL_LEAVE);
        leavePermit2.setStatus(Status.PERMIT_SUBMIT);
        leavePermit2.setUser("jettyrun2");
        StatusMachineEngine.post(leavePermit2);

        System.out.println("----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走-------");
        leavePermit2.setEvent(Event.AGREE);
        StatusMachineEngine.post(leavePermit2);


        System.out.println("----- 分割线 表明假条须要hr审批了,hr给个经过意见,而后状态机接着走-------");
        leavePermit2.setEvent(Event.AGREE);
        StatusMachineEngine.post(leavePermit2);
        System.out.println("--->>>>>>>>>end<<<<<<<<-------");

  

user:jettyrun2--病假提交--leavePermit status:permitSubmit-提交假单
user:jettyrun2--领导审批病假中--leavePermit status:leaderPermiting-领导审批中
user:jettyrun2--等待领导病假审批--leavePermit status:leaderPermiting-领导审批中
----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走-------
user:jettyrun2--领导审批病假中--leavePermit status:leaderPermiting-领导审批中
user:jettyrun2--领导赞成休病假--leavePermit status:leaderAgree-领导赞成
user:jettyrun2--hr审批病假中--leavePermit status:hrPermiting-hr审批中
user:jettyrun2--等待hr审批--leavePermit status:hrPermiting
----- 分割线 表明假条须要hr审批了,hr给个经过意见,而后状态机接着走-------
user:jettyrun2--hr审批病假中--leavePermit status:hrPermiting-hr审批中
user:jettyrun2--hr赞成休病假--leavePermit status:hrAgree-hr赞成
user:jettyrun2--成功病假审批--leavePermit status:permitSuccess-请假成功
--->>>>>>>>>end<<<<<<<<-------

  

该状态机的设计思想有一部分借鉴公司的几个项目,一部分来源于当当elastic-job的源码解读心得。
源代码地址请点击我 github

相关文章
相关标签/搜索