摘自:https://www.jianshu.com/p/8def04b34b3cjava
首先,瞭解狀態機是什麼,咱們爲何須要狀態機!
舉個最簡單例子,請假,做爲一個最底層程序員,每次請假都要領導層層審批,而假有分爲不少種,事假,病假,婚假,年休假等等,固然選擇請的假不一樣,審批標準也不一樣,不一樣的假單須要走的審批鏈也不同,好比年休假,可能只須要領導審批扣掉年休假便可,請病假須要領導審批,領導審批以後,先休假,等休完假回來提交病假的材料,由hr審批以後才能完成整個請假過程。更有甚者,若是你要修一個一個月的長假,就不只僅是須要直線領導hr審批,可能還須要公司ceo審批 ,審批經過後,才能經過。以下圖:git
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; } }
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
這塊功能能夠交給狀態機StatusMachine去解決,由當前狀態+事件驅動(也就是當前請假的狀態和審批意見)獲取下一個狀態。ui
咱們知道,請假的種類不一樣,所走的流程也不一樣,相應的處理也不一樣,每種假單都有本身的審批鏈,也對應每種假單有不一樣的狀態機,不難設計StatusMachine爲接口或抽象類。狀態機只作一件事情,根據event(審批意見),跳轉下一個狀態機。this
public interface StatusMachine { /** *@params status 當前狀態 *@params event 審批意見 *@return 下一個狀態 **/ public Status getNextStatus(Status status,Event event); }
這裏舉兩個例子,一個病假,一個年休假的實現:設計
年休假的審批流程:code
所以事假的狀態機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審批意見"); } } }
病假的審批流程:
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)); } }
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