產(chǎn)品經(jīng)理懂點(diǎn)技術(shù):狀態(tài)機(jī)
做產(chǎn)品的時(shí)候,我們總能遇到一些比較復(fù)雜的邏輯問題,而普通的流程圖,或時(shí)序圖對(duì)于對(duì)象和狀態(tài)的解讀缺乏直觀的描述。
這時(shí),推薦使用簡單的狀態(tài)圖來對(duì)邏輯問題進(jìn)行描述。
在開發(fā)過程中,如果有邏輯關(guān)系比較混亂的,我們就可以考慮使用有限狀態(tài)機(jī)來解決問題。
狀態(tài)機(jī),表示某幾種狀態(tài)之間的切換。描述一個(gè)對(duì)象從一個(gè)狀態(tài),經(jīng)過一個(gè)事件驅(qū)動(dòng)轉(zhuǎn)變?yōu)榱硪粋€(gè)狀態(tài)的過程,叫做一次狀態(tài)遷移,一個(gè)對(duì)象所具備的所有狀態(tài)遷移過程叫做狀態(tài)機(jī)。
因?yàn)闋顟B(tài)機(jī)的狀態(tài)是有限的,所以一般上也叫有限狀態(tài)機(jī)(Finite State Mache)。
利用狀態(tài)機(jī)可以精確地描述對(duì)象的行為,從對(duì)象的初始狀態(tài)起,開始響應(yīng)事件并執(zhí)行某些動(dòng)作,這些事件引起狀態(tài)的轉(zhuǎn)換,對(duì)象在新的狀態(tài)下又開始響應(yīng)狀態(tài)和執(zhí)行動(dòng)作,如此連續(xù)進(jìn)行直到終結(jié)狀態(tài)。
?
狀態(tài)機(jī)的作用
1、不需要每個(gè)接口都校驗(yàn)當(dāng)前狀態(tài):直接數(shù)據(jù)庫配置某個(gè)狀態(tài),加某個(gè)操作,才能進(jìn)行下去,如果不對(duì)的狀態(tài)進(jìn)行該操作,會(huì)報(bào)錯(cuò)
2、同一個(gè)接口配置不同的流程:同一個(gè)如審批通過的接口,不同狀態(tài)下審批不通過,需要走不同的流程,如審批中審批不通過,走改變狀態(tài)的流程,變更審批中審批不通過,走回退歷史的版本數(shù)據(jù)的流程,如果不用狀態(tài)機(jī),則需要分開寫2個(gè)接口,或者在一個(gè)接口里走if else,考慮到復(fù)雜的訂單狀態(tài)變遷觸發(fā)節(jié)點(diǎn),可能if-else會(huì)非常多,比如某5種狀態(tài)下的同一個(gè)接口走不同的流程
3、實(shí)現(xiàn)流程可配制化,高內(nèi)聚,集中配置,直接在數(shù)據(jù)庫更改配置信息,可維護(hù)性和擴(kuò)展性強(qiáng)
4、易變更,快速修改
5、易使用,極大簡化前端的代碼,是否可以刪除,變更按鈕的顯示和隱藏通過后端返回
?
狀態(tài)機(jī)由什么組成?
狀態(tài):表示一個(gè)模型在生存期內(nèi)的狀況
轉(zhuǎn)換:表示兩個(gè)不同狀態(tài)之間的聯(lián)席
事件:是在某個(gè)時(shí)間產(chǎn)生的
活動(dòng):是在狀態(tài)機(jī)中進(jìn)行的一個(gè)非原子的執(zhí)行,有一系列動(dòng)作組成
動(dòng)作:是一個(gè)可執(zhí)行的原子計(jì)算,它導(dǎo)致狀態(tài)的變更或者返回一個(gè)值
當(dāng)需要描述一個(gè)對(duì)象或系統(tǒng)的行為狀態(tài)時(shí),相比于直接的語言描述,更推薦使用狀態(tài)機(jī)表或狀態(tài)機(jī)圖的形式。
首先看一下圖形中的基本元素:
分析需求時(shí)需要了解以下六種元素:
起始
終止
現(xiàn)態(tài)
次態(tài)(目標(biāo)狀態(tài))
動(dòng)作
條件
?
這樣,我們就可以完成狀態(tài)機(jī)圖了,來看一個(gè)具體的案例吧:
1.現(xiàn)態(tài):是指當(dāng)前所處的狀態(tài)。
2.條件:又稱為“事件”,當(dāng)一個(gè)條件被滿足,將會(huì)觸發(fā)一個(gè)動(dòng)作,或者執(zhí)行一次狀態(tài)的遷移。
3.動(dòng)作:條件滿足后執(zhí)行的動(dòng)作。動(dòng)作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。動(dòng)作不是必需的,當(dāng)條件滿足后,也可以不執(zhí)行任何動(dòng)作,直接遷移到新狀態(tài)。
4.次態(tài):條件滿足后要遷往的新狀態(tài)。“次態(tài)”是相對(duì)于“現(xiàn)態(tài)”而言的,“次態(tài)”一旦被激活,就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。
?注意:
1、注意區(qū)分“程序動(dòng)作”和“狀態(tài)”。如何區(qū)分“動(dòng)作”和“狀態(tài)”?
“動(dòng)作”是不穩(wěn)定的,即使沒有條件的觸發(fā),“動(dòng)作”一旦執(zhí)行完畢就結(jié)束了;
“狀態(tài)”是相對(duì)穩(wěn)定的,如果沒有外部條件的觸發(fā),一個(gè)狀態(tài)會(huì)一直持續(xù)下去。
2、狀態(tài)劃分避免缺漏,這樣會(huì)導(dǎo)致跳轉(zhuǎn)邏輯不完整。查看狀態(tài)圖或者狀態(tài)表是很有必要的,盡量讓設(shè)計(jì)方案足夠完善。
?
如何做狀態(tài)機(jī)表?
先看案例,下面的狀態(tài)機(jī)圖展示了一個(gè)文件的狀態(tài)流轉(zhuǎn)。
將狀態(tài)圖轉(zhuǎn)為狀態(tài)表有多種制表法,如果以縱坐標(biāo)區(qū)分,有兩種:
左邊的狀態(tài)表的縱坐標(biāo)為初始狀態(tài),橫坐標(biāo)為終止?fàn)顟B(tài)。
右邊的狀態(tài)表的縱坐標(biāo)為動(dòng)作條件,橫坐標(biāo)為終止?fàn)顟B(tài)。
如果動(dòng)作多且復(fù)雜的情況下,建議采用右側(cè)表格方式,會(huì)更清晰。
狀態(tài)機(jī)圖的使用場(chǎng)景
狀態(tài)機(jī)圖常應(yīng)用在程序的設(shè)計(jì)過程中,使用清晰明了的狀態(tài)機(jī)圖設(shè)計(jì)代碼邏輯架構(gòu),再使用編程語言去實(shí)現(xiàn)。
也可以畫一個(gè)狀態(tài)機(jī)圖來展示某崗位的工作:
?
開發(fā)實(shí)現(xiàn)狀態(tài)機(jī)的設(shè)計(jì)實(shí)例
實(shí)例:電商平臺(tái)訂單狀態(tài)設(shè)計(jì)
?
狀態(tài)機(jī)的技術(shù)實(shí)現(xiàn)
首先會(huì)有2個(gè)表:flow和flow_picker表:
flow表:主要用于存放不同的流程的名字,主要會(huì)有個(gè)id,訂單走一個(gè)流,退貨單走一個(gè)流
flow_picker表:主要是每個(gè)業(yè)務(wù)創(chuàng)建的時(shí)候,會(huì)關(guān)聯(lián)到哪個(gè)flow,就是關(guān)聯(lián)到哪個(gè)流程id里,會(huì)通過來源,渠道,類型,等級(jí)等等條件,篩選出這個(gè)訂單,關(guān)聯(lián)的flow,存入訂單表里的flow_id字段
?
配置流程的表:
先會(huì)根據(jù)訂單的flow_id篩選出走哪個(gè)流程,再根據(jù)來源狀態(tài) source_status,操作operation_value,到達(dá)目標(biāo)狀態(tài)target_status,執(zhí)行action_name,
action_name是自己配置的,action_name里面的類就是不同流程,執(zhí)行的代碼
根據(jù)這個(gè)配置,初始化時(shí)注入所有的action,可以調(diào)到數(shù)據(jù)庫對(duì)應(yīng)的配置的aciton類,同一個(gè)接口,可執(zhí)行多個(gè)流程就完成了。
?