理解狀態(tài)機(jī)原理及實(shí)踐

基本概念

  • 有限狀態(tài)機(jī)FSM
  • 描述事物的有限狀態(tài)機(jī)模型的元素由以下組成:
    1. 狀態(tài)(State):事物的狀態(tài)岛琼,包括初始狀態(tài)和所有事件觸發(fā)后的狀態(tài)
    2. 事件(Event):觸發(fā)狀態(tài)變化或者保持原狀態(tài)的事件
    3. 行為或轉(zhuǎn)換(Action/Transition):執(zhí)行狀態(tài)轉(zhuǎn)換的過(guò)程
    4. 檢測(cè)器(Guard):檢測(cè)某種狀態(tài)要轉(zhuǎn)換成另一種狀態(tài)的條件是否滿(mǎn)足
  • http://www.reibang.com/p/37281543f506
  • 深入淺出理解有限狀態(tài)機(jī)
  • 狀態(tài)機(jī)的要素
  • 狀態(tài)機(jī)可歸納為4個(gè)要素,即現(xiàn)態(tài)、條件奔缠、動(dòng)作蚕冬、次態(tài)浩考。“現(xiàn)態(tài)”和“條件”是因办陷,“動(dòng)作”和“次態(tài)”是果。詳解如下:
    1. 現(xiàn)態(tài):是指當(dāng)前所處的狀態(tài)律歼。
    2. 條件:又稱(chēng)為“事件”民镜。當(dāng)一個(gè)條件被滿(mǎn)足,將會(huì)觸發(fā)一個(gè)動(dòng)作苗膝,或者執(zhí)行一次狀態(tài)的遷移殃恒。
    3. 動(dòng)作:條件滿(mǎn)足后執(zhí)行的動(dòng)作。動(dòng)作執(zhí)行完畢后辱揭,可以遷移到新的狀態(tài)离唐,也可以仍舊保持原狀態(tài)。動(dòng)作不是必需的问窃,當(dāng)條件滿(mǎn)足后亥鬓,也可以不執(zhí)行任何動(dòng)作,直接遷移到新?tīng)顟B(tài)域庇。
    4. 次態(tài):條件滿(mǎn)足后要遷往的新?tīng)顟B(tài)嵌戈。“次態(tài)”是相對(duì)于“現(xiàn)態(tài)”而言的听皿,“次態(tài)”一旦被激活熟呛,就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。

代碼實(shí)現(xiàn)

  1. 定義狀態(tài)
public enum ProcessState {

    INIT(0, "未開(kāi)始"),
    READY_ONE_SIDE(1, "一方準(zhǔn)備完成"),
    READY_ALL(2, "雙方準(zhǔn)備完成"),
    CHAT(3, "發(fā)言完成"),
    END(4, "結(jié)束"),
    ;

    private int val;
    private String desc;

    ProcessState(int val, String desc) {
        this.val = val;
        this.desc = desc;
    }

    public int getVal() {
        return val;
    }
}
  1. 定義事件
public enum ProcessEvent {

    READY_ONE_SIDE(1, "一方準(zhǔn)備"),
        READY_ALL(2, "另一方準(zhǔn)備"),
        CHAT(3, "發(fā)言"),
        FORBID_ALL(4, "全員禁言"),
    ;
    
    private Integer code;
    private String desc;

    ProcessEvent(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public Integer getCode() {
        return code;
    }
}
  1. 定義狀態(tài)機(jī)
public class ProcessEventConfig {

    private ProcessEvent event;
    private ProcessState fromState;
    private ProcessState toState;

    public String desc(){
        return fromState.getDesc() + "_" + event.getDesc() + "_" + toState.getDesc();
    }
}


List<ProcessEventConfig> configList = new ArrayList<>(16);
configList.add(new ProcessEventConfig(ProcessEvent.READY_ONE_SIDE, ProcessState.INIT, ProcessState.READY_ONE_SIDE));
configList.add(new ProcessEventConfig(ProcessEvent.READY_ALL, ProcessState.READY_ONE_SIDE, ProcessState.READY_ALL));
configList.add(new ProcessEventConfig(ProcessEvent.CHAT, ProcessState.READY_ALL, ProcessState.CHAT));
configList.add(new ProcessEventConfig(ProcessEvent.FORBID_ALL, ProcessState.CHAT, ProcessState.END));

Map<ProcessEvent, ProcessEventConfig> eventResultStateConfigMap = new EnumMap<>(ProcessEvent.class);

configList.forEach(eventConfig -> eventResultStateConfigMap.put(eventConfig.getEvent(), eventConfig));

  1. 觸發(fā)狀態(tài)變化
public boolean fire(ProcessEvent event, Process process) {

        ProcessEventConfig config = Optional.ofNullable(eventResultStateConfigMap.get(event)).orElseThrow(() -> ExceptionCodeEnum.AGRS_INVALID.newException("不存在該事件"));

        if (process.getStatus() != config.getFromState().getVal()) {
            return false;
        }
        process.setRemark(config.desc());
        process.setStatus(config.getToState().getVal());

                //DB改變狀態(tài)
                /*update table set status=${status} WHERE id={id} AND status=${beforeStatus}*/
        boolean suc = processManager.updateStatus(process, config.getFromState().getVal());
        if (suc) {
               //變更成功尉姨,業(yè)務(wù)邏輯    
        }
        return suc;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末庵朝,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌九府,老刑警劉巖椎瘟,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異侄旬,居然都是意外死亡肺蔚,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)儡羔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宣羊,“玉大人,你說(shuō)我怎么就攤上這事笔链《沃唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵鉴扫,是天一觀的道長(zhǎng)赞枕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)坪创,這世上最難降的妖魔是什么炕婶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮莱预,結(jié)果婚禮上柠掂,老公的妹妹穿的比我還像新娘。我一直安慰自己依沮,他們只是感情好涯贞,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著危喉,像睡著了一般宋渔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辜限,一...
    開(kāi)封第一講書(shū)人閱讀 51,708評(píng)論 1 305
  • 那天皇拣,我揣著相機(jī)與錄音,去河邊找鬼薄嫡。 笑死氧急,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毫深。 我是一名探鬼主播吩坝,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哑蔫!你這毒婦竟也來(lái)了钾恢?” 一聲冷哼從身側(cè)響起手素,我...
    開(kāi)封第一講書(shū)人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘩蚪,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體稿黍,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡疹瘦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了巡球。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片言沐。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖酣栈,靈堂內(nèi)的尸體忽然破棺而出险胰,到底是詐尸還是另有隱情,我是刑警寧澤矿筝,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布起便,位于F島的核電站,受9級(jí)特大地震影響窖维,放射性物質(zhì)發(fā)生泄漏榆综。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一铸史、第九天 我趴在偏房一處隱蔽的房頂上張望鼻疮。 院中可真熱鬧,春花似錦琳轿、人聲如沸判沟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挪哄。三九已至,卻和暖如春媚送,著一層夾襖步出監(jiān)牢的瞬間中燥,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工塘偎, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疗涉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓吟秩,卻偏偏與公主長(zhǎng)得像咱扣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涵防,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容