天天看點

Enum枚舉寫的一個簡單狀态機

今天下雨,心情有點壓抑,是以用枚舉寫個狀态機排解一下心情,順便記錄一下枚舉使用方法.

package statemachine;

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

/**
 * 
 * @author ZhenWeiLai
 *
 */
public enum StateEnum {

    READY("1", "準備"){
        @Override
        void submit(Entity entity) {
            super.submit(entity);
            //重寫更新狀态方法,加入自己的業務邏輯
            System.out.println("Ready submit 收尾工作...");
        }
    },
    START("2", "開始"){
        @Override
        void undo(Entity entity) {
            super.undo(entity);
            System.out.println("Start undo 收尾工作...");
        }
    },
    RUN("3", "運作"),
    STOP("4", "停止");

    //狀态代碼
    private String code;
    //狀态名稱
    private String name;
    
    //構造方法
    StateEnum(String code, String name){
        this.code = code;
        this.name = name;
        //構造時把代碼注冊進清單
        StateList.stateList.add(code);
    }

    //更新狀态的方法,如果更新狀态需要做什麼其他操作,那麼重寫該方法,然後super調用,再加入自己邏輯
    void submit(Entity entity) {
        if (entity.getState() == null && !this.getCode().equals(READY.getCode()))
            throw new RuntimeException("狀态不合法");
        else if(entity.getState() == null && this.getCode().equals(READY.getCode())){
            entity.setState(StateList.stateList.get(0));
            return;
        }
            
        if(!StateList.stateList.get((StateList.stateList.indexOf(entity.getState())+1)).equals(this.code))
            throw new RuntimeException("狀态不合法");
        
        if(StateList.stateList.contains(this.code)){
            entity.setState(this.code);
        }
    }

    //反操作方法,與送出方法同理
    void undo(Entity entity) {
        //如果目前沒有狀态,也不是目前枚舉狀态,那麼抛出異常
        if (entity.getState() == null||!entity.getState().equals(this.code))
            throw new RuntimeException("狀态不合法");
        //判斷是否已經注冊進清單的合法狀态
            if(StateList.stateList.contains(this.code)){
                Integer codeIndex = StateList.stateList.indexOf(this.code);
                //如果不是初始化狀态,那麼回退一個狀态,否則設定為null
                if(codeIndex>0)
                    entity.setState(StateList.stateList.get(--codeIndex));
                else
                    entity.setState(null);
            }
    }
    
    //根據code擷取狀态名稱
    public static String getNameByCode(String code){
        for(StateEnum item : StateEnum.values()){
            if(item.getCode().equals(code)){
                return item.getName();
            }
        }
         return "";
    }
    
    /**
     * 
     * @author ZhenWeiLai
     * 靜态内部類,挺環保的,為了使用這個靜态list
     * 因為枚舉構造方法不能調用靜态屬性,原因不明,知道的人請告訴我一聲
     */
    static class StateList{
        private static List<String> stateList = new ArrayList<>();
    }
    
    //------------------------------------------------------getter setter-------------------------------------------------------------------------

    
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}      
package statemachine;

/**
 * 
 * @author ZhenWeiLai
 * 實體
 */
public class Entity {
    //狀态code
    private String state;
    
    /**
     * 擷取狀态code轉譯
     * @return
     */
    public String getStateName(){
        return StateEnum.getNameByCode(this.state);
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
    }
}      
package statemachine;

/**
 * 
 * @author ZhenWeiLai
 *
 */
public class TestClass {
    
    /**
     * 測試方法
     * @param args
     */
    public static void main(String[] args) {
        Entity entity = new Entity();

        StateEnum.READY.submit(entity);
        System.out.println(entity.getStateName());
        StateEnum.START.submit(entity);
        System.out.println(entity.getStateName());
        StateEnum.RUN.submit(entity);
        System.out.println(entity.getStateName());
        StateEnum.STOP.submit(entity);
        System.out.println(entity.getStateName());
        
        StateEnum.STOP.undo(entity);
        System.out.println(entity.getStateName());
        StateEnum.RUN.undo(entity);
        System.out.println(entity.getStateName());
        StateEnum.START.undo(entity);
        System.out.println(entity.getStateName());
        StateEnum.READY.undo(entity);
        System.out.println(entity.getStateName());
    
    }
}      

控制台輸出結果:

Ready submit 收尾工作...
準備
開始
運作
停止
運作
開始
Start undo 收尾工作...
準備      

繼續閱讀