国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

金山石化網站建設襄陽seo優(yōu)化排名

金山石化網站建設,襄陽seo優(yōu)化排名,杭州做商業(yè)地產開什么網站好,網站建設公司名稱一、狀態(tài)機 1. 定義 有限狀態(tài)機(Finite-state machine, FSM),簡稱狀態(tài)機,是表示有限個狀態(tài)以及在這些狀態(tài)之間的轉移和動作等行為的數(shù)學模型。 2. 組成要素 現(xiàn)態(tài)(src state):事務當前所處的狀…

一、狀態(tài)機

1. 定義

有限狀態(tài)機(Finite-state machine, FSM),簡稱狀態(tài)機,是表示有限個狀態(tài)以及在這些狀態(tài)之間的轉移和動作等行為的數(shù)學模型。

2. 組成要素

  • 現(xiàn)態(tài)(src state):事務當前所處的狀態(tài)。

  • 事件(event):事件就是執(zhí)行某個操作的觸發(fā)條件,當一個事件被滿足,將會觸發(fā)一個動作,或者執(zhí)行一次狀態(tài)的遷移。

  • 動作(action):事件滿足后執(zhí)行的動作。動作執(zhí)行完畢后,可以遷移到新的狀態(tài),也可以仍舊保持原狀態(tài)。動作不是必需的,當事件滿足后,也可以不執(zhí)行任何動作,直接遷移到新狀態(tài)。

  • 次態(tài)(dst state):事件滿足后要遷往的新狀態(tài)?!按螒B(tài)”是相對于“現(xiàn)態(tài)”而言的,“次態(tài)”一旦被激活,就轉變成新的“現(xiàn)態(tài)”了。

  • 狀態(tài)流轉(transition):事物從現(xiàn)態(tài)轉為次態(tài)的整個過程。

3. 優(yōu)點

  • 代碼抽象:將業(yè)務流程進行抽象和結構化,將復雜的狀態(tài)轉移圖,分割成相鄰狀態(tài)的最小單元。這樣相當于搭建樂高積木,在這套機制上可以組合成復雜的狀態(tài)轉移圖,同時隱藏了系統(tǒng)的復雜度。
  • 簡化流程:業(yè)務rd只需要關注當前操作的業(yè)務邏輯(狀態(tài)流轉過程中的業(yè)務回調函數(shù)),極大的解耦了狀態(tài)和業(yè)務。
  • 易擴展:在新增狀態(tài)或事件時,無需修改原有的狀態(tài)流轉邏輯,直接建立新的狀態(tài)轉移鏈路即可。
  • 業(yè)務建模:通過最小粒度的相鄰狀態(tài)拼接,最終組成了業(yè)務的整體graph。

二、代碼

請?zhí)砑訄D片描述

假設我們有要實現(xiàn)一個訂單下單功能,上圖是訂單狀態(tài)的流轉圖,方框為訂單的狀態(tài),箭頭旁的文字為事件。

1. database包

package databaseimport "fmt"// DB 模擬數(shù)據(jù)庫對象
type DB struct {
}// Transaction 模擬事務
func (db *DB) Transaction(fun func() error) error {fmt.Println("事務執(zhí)行開始。")err := fun()fmt.Println("事務執(zhí)行結束。")return err
}// Order 訂單
type Order struct {ID    int64 // 主鍵IDState int   // 狀態(tài)
}type OrderList []*Order// 查詢所有訂單
func ListAllOrder() (OrderList, error) {orderList := OrderList{&Order{1, 0},&Order{2, 1},&Order{2, 2},}return orderList, nil
}// UpdateOrderState 更新訂單狀態(tài)
func UpdateOrderState(curOrder *Order, srcState int, dstState int) error {if curOrder.State == srcState {curOrder.State = dstState}fmt.Printf("更新id為 %v 的訂單狀態(tài),從現(xiàn)態(tài)[%v]到次態(tài)[%v]\n", curOrder.ID, srcState, dstState)return nil
}

用來模擬數(shù)據(jù)庫的操作,如數(shù)據(jù)庫事務、查詢所有訂單、更新訂單狀態(tài)等。

2. fsm包

package fsmimport ("fmt""reflect""zuzhiang/database"
)// FSMState 狀態(tài)機的狀態(tài)類型
type FSMState int// FSMEvent 狀態(tài)機的事件類型
type FSMEvent string// FSMTransitionMap 狀態(tài)機的狀態(tài)轉移圖類型,現(xiàn)態(tài)和事件一旦確定,次態(tài)和動作就唯一確定
type FSMTransitionMap map[FSMState]map[FSMEvent]FSMDstStateAndAction// FSMTransitionFunc 狀態(tài)機的狀態(tài)轉移函數(shù)類型
type FSMTransitionFunc func(params map[string]interface{}, srcState FSMState, dstState FSMState) error// FSMDstStateAndAction 狀態(tài)機的次態(tài)和動作
type FSMDstStateAndAction struct {DstState FSMState  // 次態(tài)Action   FSMAction // 動作
}// FSMAction 狀態(tài)機的動作
type FSMAction interface {Before(bizParams map[string]interface{}) error                   // 狀態(tài)轉移前執(zhí)行Execute(bizParams map[string]interface{}, tx *database.DB) error // 狀態(tài)轉移中執(zhí)行After(bizParams map[string]interface{}) error                    // 狀態(tài)轉移后執(zhí)行
}// FSM 狀態(tài)機,元素均為不可導出
type FSM struct {transitionMap  FSMTransitionMap  // 狀態(tài)轉移圖transitionFunc FSMTransitionFunc // 狀態(tài)轉移函數(shù)
}// CreateNewFSM 創(chuàng)建一個新的狀態(tài)機
func CreateNewFSM(transitionFunc FSMTransitionFunc) *FSM {return &FSM{transitionMap:  make(FSMTransitionMap),transitionFunc: transitionFunc,}
}// SetTransitionMap 設置狀態(tài)機的狀態(tài)轉移圖
func (fsm *FSM) SetTransitionMap(srcState FSMState, event FSMEvent, dstState FSMState, action FSMAction) {if int(srcState) < 0 || len(event) <= 0 || int(dstState) < 0 {panic("現(xiàn)態(tài)|事件|次態(tài)非法。")return}transitionMap := fsm.transitionMapif transitionMap == nil {transitionMap = make(FSMTransitionMap)}if _, ok := transitionMap[srcState]; !ok {transitionMap[srcState] = make(map[FSMEvent]FSMDstStateAndAction)}if _, ok := transitionMap[srcState][event]; !ok {dstStateAndAction := FSMDstStateAndAction{DstState: dstState,Action:   action,}transitionMap[srcState][event] = dstStateAndAction} else {fmt.Printf("現(xiàn)態(tài)[%v]+事件[%v]+次態(tài)[%v]已定義過,請勿重復定義。\n", srcState, event, dstState)return}fsm.transitionMap = transitionMap
}// Push 狀態(tài)機的狀態(tài)遷移
func (fsm *FSM) Push(tx *database.DB, params map[string]interface{}, currentState FSMState, event FSMEvent) error {// 根據(jù)現(xiàn)態(tài)和事件從狀態(tài)轉移圖獲取次態(tài)和動作transitionMap := fsm.transitionMapevents, eventExist := transitionMap[currentState]if !eventExist {return fmt.Errorf("現(xiàn)態(tài)[%v]未配置遷移事件", currentState)}dstStateAndAction, ok := events[event]if !ok {return fmt.Errorf("現(xiàn)態(tài)[%v]+遷移事件[%v]未配置次態(tài)", currentState, event)}dstState := dstStateAndAction.DstStateaction := dstStateAndAction.Action// 執(zhí)行before方法if action != nil {fsmActionName := reflect.ValueOf(action).String()fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], [%v].before\n", currentState, event, dstState, fsmActionName)if err := action.Before(params); err != nil {return fmt.Errorf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v]失敗, [%v].before, err: %v", currentState, event, dstState, fsmActionName, err)}}// 事務執(zhí)行execute方法和transitionFuncif tx == nil {tx = new(database.DB)}transactionErr := tx.Transaction(func() error {fsmActionName := reflect.ValueOf(action).String()fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], [%v].execute\n", currentState, event, dstState, fsmActionName)if action != nil {if err := action.Execute(params, tx); err != nil {return fmt.Errorf("狀態(tài)轉移執(zhí)行出錯:%v", err)}}fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], transitionFunc\n", currentState, event, dstState)if err := fsm.transitionFunc(params, currentState, dstState); err != nil {return fmt.Errorf("執(zhí)行狀態(tài)轉移函數(shù)出錯: %v", err)}return nil})if transactionErr != nil {return transactionErr}// 執(zhí)行after方法if action != nil {fsmActionName := reflect.ValueOf(action).String()fmt.Printf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v], [%v].after\n", currentState, event, dstState, fsmActionName)if err := action.After(params); err != nil {return fmt.Errorf("現(xiàn)態(tài)[%v]+遷移事件[%v]->次態(tài)[%v]失敗, [%v].before, err: %v", currentState, event, dstState, fsmActionName, err)}}return nil
}

狀態(tài)機包含的元素有兩個:狀態(tài)轉移圖和狀態(tài)轉移函數(shù),為了防止包外直接調用,這兩個元素都設為了不可導出的。狀態(tài)轉移圖說明了狀態(tài)機的狀態(tài)流轉情況,狀態(tài)轉移函數(shù)定義了在狀態(tài)轉移的過程中需要做的事情,在創(chuàng)建狀態(tài)時指定,如更新數(shù)據(jù)庫實體(order)的狀態(tài)。

而狀態(tài)轉移圖又包含現(xiàn)態(tài)、事件、次態(tài)和動作,一旦現(xiàn)態(tài)和事件確定,那么狀態(tài)流轉的唯一次態(tài)和動作就隨之確定。

狀態(tài)機的動作又包含三個:Before、Execute和After。Before操作在是事務前執(zhí)行,由于此時沒有翻狀態(tài),所以該步可能會被重復執(zhí)行。Execute操作是和狀態(tài)轉移函數(shù)在同一事務中執(zhí)行的,同時成功或同時失敗。After操作是在事務后執(zhí)行,因為在執(zhí)行前狀態(tài)已經翻轉,所以最多會執(zhí)行一次,在業(yè)務上允許執(zhí)行失敗或未執(zhí)行。

狀態(tài)機的主要方法有兩個,SetTransitionMap方法用來設置狀態(tài)機的狀態(tài)轉移圖,Push方法用來根據(jù)現(xiàn)態(tài)和事件推動狀態(tài)機進行狀態(tài)翻轉。Push方法中會先執(zhí)行Before動作,再在同一事務中執(zhí)行Execute動作和狀態(tài)轉移函數(shù),最后執(zhí)行After動作。在執(zhí)行Push方法的時候會將params參數(shù)傳遞給狀態(tài)轉移函數(shù)。

3. order包

(1) order

package orderimport ("fmt""zuzhiang/database""zuzhiang/fsm"
)var (// 狀態(tài)StateOrderInit          = fsm.FSMState(0) // 初始狀態(tài)StateOrderToBePaid      = fsm.FSMState(1) // 待支付StateOrderToBeDelivered = fsm.FSMState(2) // 待發(fā)貨StateOrderCancel        = fsm.FSMState(3) // 訂單取消StateOrderToBeReceived  = fsm.FSMState(4) // 待收貨StateOrderDone          = fsm.FSMState(5) // 訂單完成// 事件EventOrderPlace      = fsm.FSMEvent("EventOrderPlace")      // 下單EventOrderPay        = fsm.FSMEvent("EventOrderPay")        // 支付EventOrderPayTimeout = fsm.FSMEvent("EventOrderPayTimeout") // 支付超時EventOrderDeliver    = fsm.FSMEvent("EventOrderDeliver")    // 發(fā)貨EventOrderReceive    = fsm.FSMEvent("EventOrderReceive")    // 收貨
)var orderFSM *fsm.FSM// orderTransitionFunc 訂單狀態(tài)轉移函數(shù)
func orderTransitionFunc(params map[string]interface{}, srcState fsm.FSMState, dstState fsm.FSMState) error {// 從params中解析order參數(shù)key, ok := params["order"]if !ok {return fmt.Errorf("params[\"order\"]不存在。")}curOrder := key.(*database.Order)fmt.Printf("order.ID: %v, order.State: %v\n", curOrder.ID, curOrder.State)// 訂單狀態(tài)轉移if err := database.UpdateOrderState(curOrder, int(srcState), int(dstState)); err != nil {return err}return nil
}// Init 狀態(tài)機的狀態(tài)轉移圖初始化
func Init() {orderFSM = fsm.CreateNewFSM(orderTransitionFunc)orderFSM.SetTransitionMap(StateOrderInit, EventOrderPlace, StateOrderToBePaid, PlaceAction{})                  // 初始化+下單 -> 待支付orderFSM.SetTransitionMap(StateOrderToBePaid, EventOrderPay, StateOrderToBeDelivered, PayAction{})             // 待支付+支付 -> 待發(fā)貨orderFSM.SetTransitionMap(StateOrderToBePaid, EventOrderPayTimeout, StateOrderCancel, nil)                     // 待支付+支付超時 -> 訂單取消orderFSM.SetTransitionMap(StateOrderToBeDelivered, EventOrderDeliver, StateOrderToBeReceived, DeliverAction{}) // 待發(fā)貨+發(fā)貨 -> 待收貨orderFSM.SetTransitionMap(StateOrderToBeReceived, EventOrderReceive, StateOrderDone, ReceiveAction{})          // 待收貨+收貨 -> 訂單完成
}// ExecOrderTask 執(zhí)行訂單任務,推動狀態(tài)轉移
func ExecOrderTask(params map[string]interface{}) error {// 從params中解析order參數(shù)key, ok := params["order"]if !ok {return fmt.Errorf("params[\"order\"]不存在。")}curOrder := key.(*database.Order)// 初始化+下單 -> 待支付if curOrder.State == int(StateOrderInit) {if err := orderFSM.Push(nil, params, StateOrderInit, EventOrderPlace); err != nil {return err}}// 待支付+支付 -> 待發(fā)貨if curOrder.State == int(StateOrderToBePaid) {if err := orderFSM.Push(nil, params, StateOrderToBePaid, EventOrderPay); err != nil {return err}}// 待支付+支付超時 -> 訂單取消if curOrder.State == int(StateOrderToBePaid) {if err := orderFSM.Push(nil, params, StateOrderToBePaid, EventOrderPayTimeout); err != nil {return err}}// 待發(fā)貨+發(fā)貨 -> 待收貨if curOrder.State == int(StateOrderToBeDelivered) {if err := orderFSM.Push(nil, params, StateOrderToBeDelivered, EventOrderDeliver); err != nil {return err}}// 待收貨+收貨 -> 訂單完成if curOrder.State == int(StateOrderToBeReceived) {if err := orderFSM.Push(nil, params, StateOrderToBeReceived, EventOrderReceive); err != nil {return err}}return nil
}

order包中做的事情主要有:

  • 定義訂單狀態(tài)機的狀態(tài)和事件;
  • 創(chuàng)建一個狀態(tài)機,并設置狀態(tài)轉移函數(shù)和狀態(tài)轉移圖;
  • 執(zhí)行訂單任務,推動狀態(tài)轉移。

(2) order_action_place

package orderimport ("fmt""zuzhiang/database"
)type PlaceAction struct {
}// Before 事務前執(zhí)行,業(yè)務上允許多次操作
func (receiver PlaceAction) Before(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行下單的Before方法。")return nil
}// Execute 事務中執(zhí)行,與狀態(tài)轉移在同一事務中
func (receiver PlaceAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {fmt.Println("執(zhí)行下單的Execute方法。")return nil
}// After 事務后執(zhí)行,業(yè)務上允許執(zhí)行失敗或未執(zhí)行
func (receiver PlaceAction) After(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行下單的After方法。")return nil
}

(2) ~ (5)是訂單不同動作的聲明和實現(xiàn)。

(3) order_action_pay

package orderimport ("fmt""zuzhiang/database"
)type PayAction struct {
}// Before 事務前執(zhí)行,業(yè)務上允許多次操作
func (receiver PayAction) Before(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行支付的Before方法。")return nil
}// Execute 事務中執(zhí)行,與狀態(tài)轉移在同一事務中
func (receiver PayAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {fmt.Println("執(zhí)行支付的Execute方法。")return nil
}// After 事務后執(zhí)行,業(yè)務上允許執(zhí)行失敗或未執(zhí)行
func (receiver PayAction) After(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行支付的After方法。")return nil
}

(4) order_action_deliver

package orderimport ("fmt""zuzhiang/database"
)type DeliverAction struct {
}// Before 事務前執(zhí)行,業(yè)務上允許多次操作
func (receiver DeliverAction) Before(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行發(fā)貨的Before方法。")return nil
}// Execute 事務中執(zhí)行,與狀態(tài)轉移在同一事務中
func (receiver DeliverAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {fmt.Println("執(zhí)行發(fā)貨的Execute方法。")return nil
}// After 事務后執(zhí)行,業(yè)務上允許執(zhí)行失敗或未執(zhí)行
func (receiver DeliverAction) After(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行發(fā)貨的After方法。")return nil
}

(5) order_action_receive

package orderimport ("fmt""zuzhiang/database"
)type ReceiveAction struct {
}// Before 事務前執(zhí)行,業(yè)務上允許多次操作
func (receiver ReceiveAction) Before(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行收貨的Before方法。")return nil
}// Execute 事務中執(zhí)行,與狀態(tài)轉移在同一事務中
func (receiver ReceiveAction) Execute(bizParams map[string]interface{}, tx *database.DB) error {fmt.Println("執(zhí)行收貨的Execute方法。")return nil
}// After 事務后執(zhí)行,業(yè)務上允許執(zhí)行失敗或未執(zhí)行
func (receiver ReceiveAction) After(bizParams map[string]interface{}) error {fmt.Println("執(zhí)行收貨的After方法。")return nil
}

4. main包

package mainimport ("fmt""zuzhiang/database""zuzhiang/order"
)func main() {order.Init()orderList, dbErr := database.ListAllOrder()if dbErr != nil {return}for _, curOrder := range orderList {params := make(map[string]interface{})params["order"] = curOrderif err := order.ExecOrderTask(params); err != nil {fmt.Printf("執(zhí)行訂單任務出錯:%v\n", err)}fmt.Println("\n\n")}
}

最后在main包里先初始化一個訂單狀態(tài)機,查詢所有訂單,并使用狀態(tài)機執(zhí)行訂單任務,推動訂單狀態(tài)轉移。注意多個訂單可以用同一個狀態(tài)機來進行狀態(tài)的遷移。

三、個人總結

為什么要使用狀態(tài)機,我想主要是它可以對一個復雜的業(yè)務流程進行模塊化拆分,使得代碼更為易讀。并且擴展性更好,如果后續(xù)有新狀態(tài)加入,只需要在原來的基礎上進行擴展即可,甚至不需要了解整個業(yè)務流程。

其次,它將數(shù)據(jù)庫實體的狀態(tài)流轉進行了模范化,避免了不同的開發(fā)人員在寫更新數(shù)據(jù)庫實體狀態(tài)代碼時可能導致的問題。

http://m.aloenet.com.cn/news/41766.html

相關文章:

  • 做網站建設的上市公司有哪些百度競價是seo還是sem
  • lamp網站開發(fā) pdf企業(yè)網站建設需求分析
  • 做便民工具網站怎么樣百度問答兼職怎么做
  • 網站怎么防采集如何推廣普通話
  • 長子營網站建設產品優(yōu)化是什么意思
  • 做3d模型的叫什么牛的網站磁力鏈搜索引擎入口
  • 黃色風格網站模板商城小程序
  • 十堰網站建設兼職發(fā)軟文的平臺
  • 長沙的互聯(lián)網網站公司營銷培訓方案
  • 門戶網站系統(tǒng)設計sem全稱
  • wordpress qq客服代碼seo有什么作用
  • 廣州網站提升排名百度指數(shù)使用指南
  • 做發(fā)票網站淘寶如何刷關鍵詞增加權重
  • 可視化網站建設軟件百度競價品牌廣告
  • 專業(yè) 網站設計公司外貿網站seo教程
  • 北京公司網站建設價格廣州網站制作服務
  • 貴州省建設廳二建報名網站全球疫情最新數(shù)據(jù)
  • 做證書的網站廈門seo推廣外包
  • 網站開發(fā)功能需求表百度關鍵詞優(yōu)化軟件
  • 南通網站關鍵詞優(yōu)化發(fā)稿吧
  • 裝修網站開發(fā)前的準備工作百度推廣一個月多少錢
  • pc網站是什么seo網頁優(yōu)化培訓
  • 網站備案跟域名備案廣告文案經典范例200字
  • 一個網站按鈕怎么做精準的搜索引擎優(yōu)化
  • 國家市場監(jiān)督管理總局60號令百度seo排名原理
  • 湛江高端網站建設頁面優(yōu)化的方法
  • 在線做字網站百度一下app下載安裝
  • 電子商務物流網站建設信息推廣平臺有哪些
  • 三河市建設廳公示網站百度的seo關鍵詞優(yōu)化怎么弄
  • 鞍山人才招聘網上海網站seo策劃