<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>



        很多業(yè)務(wù)系統(tǒng)開(kāi)發(fā)中,不可避免的會(huì)出現(xiàn)狀態(tài)變化,通常采用的情形可能是使用工作流去完成,但是對(duì)于簡(jiǎn)單場(chǎng)景下,用工作流有點(diǎn)大財(cái)小用感覺(jué),比如訂單業(yè)務(wù)中,訂單狀態(tài)的變更,涉及到的狀態(tài)量不是很多,即使通過(guò)簡(jiǎn)單的if-else也能足夠使用,甚至是用上switch去減少if-else的使用,都是可以的,盡管這會(huì)喪失某些東西。為更好的優(yōu)化整個(gè)流程,此時(shí)會(huì)考慮到使用狀態(tài)模式來(lái)解決一些問(wèn)題。

        Stateless狀態(tài)機(jī)GitHub:https://github.com/dotnet-state-machine/stateless
      <https://github.com/dotnet-state-machine/stateless>?

      ?

      一、狀態(tài)模式與狀態(tài)機(jī)

      1、狀態(tài)模式:"允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為。對(duì)象看起來(lái)似乎修改了它所屬的類(lèi) "。 (State Pattern:?"Allow an
      object to alter its behavior when its internal state changes. The object will
      appear to change its class?".)


        對(duì)于這個(gè)定義,有點(diǎn)抽象,變通理解一下可以這么理解:狀態(tài)擁有者將變更行為委托給狀態(tài)對(duì)象,狀態(tài)擁有者本身只擁有狀態(tài)(當(dāng)然也可以拋棄狀態(tài)對(duì)象),狀態(tài)對(duì)象履行變更職責(zé)。

      ?

      2、狀態(tài)機(jī):"依照指定的狀態(tài)流程圖,根據(jù)當(dāng)前執(zhí)行的動(dòng)作,將當(dāng)前狀態(tài)按照預(yù)定的條件變更到新的狀態(tài)?"。

        狀態(tài)機(jī)有4個(gè)要素,即現(xiàn)態(tài)、條件、動(dòng)作、次態(tài)。其中,現(xiàn)態(tài)和條件是“因”, 動(dòng)作和次態(tài)是“果”。

      * 現(xiàn)態(tài) - 是指當(dāng)前對(duì)象的狀態(tài)
      * 條件 - 當(dāng)一個(gè)條件滿足時(shí),當(dāng)前對(duì)象會(huì)觸發(fā)一個(gè)動(dòng)作
      * 動(dòng)作 - 條件滿足之后,執(zhí)行的動(dòng)作
      * 次態(tài) - 條件滿足之后,當(dāng)前對(duì)象的新?tīng)顟B(tài)。次態(tài)是相對(duì)現(xiàn)態(tài)而言的,次態(tài)一旦觸發(fā),就變成了現(xiàn)態(tài)
      ?

      3、狀態(tài)遷移圖:"
      在UML建模中,常??梢?jiàn),用來(lái)描述一個(gè)特定的對(duì)象所有可能的狀態(tài),以及由于各種事件的發(fā)生而引起的狀態(tài)之間的轉(zhuǎn)移和變化,也是配置狀態(tài)機(jī)按照何種行徑的前提"。

        

      ?

      二、Stateless功能介紹

        Stateless是一個(gè)基于C#創(chuàng)建狀態(tài)機(jī)的簡(jiǎn)單庫(kù)?;?Net Standard實(shí)現(xiàn),在.Net Framework和.Net
      Core項(xiàng)目中都可以使用。源碼地址:https://github.com/dotnet-state-machine/stateless
      <https://github.com/dotnet-state-machine/stateless>。

        以一個(gè)打電話的使用案例來(lái)講講Stateless的功能:
      //初始化狀態(tài)機(jī) var phoneCall = new StateMachine<State, Trigger>(State.OffHook); //
      流程配置 phoneCall.Configure(State.OffHook) .Permit(Trigger.CallDialled,
      State.Ringing); phoneCall.Configure(State.Ringing)
      .Permit(Trigger.CallConnected, State.Connected);
      phoneCall.Configure(State.Connected) .OnEntry(()=> StartCallTimer()) .OnExit(()
      => StopCallTimer()) .Permit(Trigger.LeftMessage, State.OffHook)
      .Permit(Trigger.PlacedOnHold, State.OnHold);// ... //觸發(fā)行為
      phoneCall.Fire(Trigger.CallDialled); Assert.AreEqual(State.Ringing,
      phoneCall.Stat
      ?

      1、功能特性

       狀態(tài)機(jī)常見(jiàn)功能:

      * 支持所有.Net類(lèi)型的狀態(tài)和觸發(fā)器(數(shù)字、字符串、枚舉等等)
      * 分層狀態(tài)
      * 狀態(tài)的進(jìn)入和退出事件
      * 用衛(wèi)語(yǔ)句來(lái)支持條件轉(zhuǎn)換
      * 內(nèi)省
       提供了一些有用的擴(kuò)展:

      * 支持外部的狀態(tài)存儲(chǔ)(例如:由ORM跟蹤屬性)
      * 參數(shù)化觸發(fā)器
      * 可重入狀態(tài)
      * 導(dǎo)出DOT格式圖
      ?

      2、分層狀態(tài)


        在以下例子中,OnHold狀態(tài)是Connected狀態(tài)的子狀態(tài)。這意味著電話掛起的時(shí)候,還是連接狀態(tài)的,通過(guò)IsInState()方法,可以判定是否當(dāng)前狀態(tài)處于父狀態(tài)下的子狀態(tài),比如IsInState(State.Connected)能夠返回true,說(shuō)明當(dāng)前OnHold狀態(tài)是處于Connected狀態(tài)的。
      phoneCall.Configure(State.OnHold) .SubstateOf(State.Connected)
      .Permit(Trigger.TakenOffHold, State.Connected)
      .Permit(Trigger.PhoneHurledAgainstWall, State.PhoneDestroyed);
      ?

      3、狀態(tài)的進(jìn)入和退出事件


        在前面的例子中,StartCallTimer()方法會(huì)在通話連接時(shí)執(zhí)行,StopCallTimer()方法會(huì)在通話結(jié)束時(shí)執(zhí)行,對(duì)應(yīng)的便是,進(jìn)入該狀態(tài)與脫離該狀態(tài)時(shí)候執(zhí)行的事件。當(dāng)電話的狀態(tài)從已連接(Connected)變?yōu)閽炱?OnHold)時(shí),
      不會(huì)觸發(fā)StartCallTimer()方法和StopCallTimer()方法,
      這是因?yàn)镺nHold是Connected的子狀態(tài),對(duì)于進(jìn)入和退出事件的處理者,可以傳參提供觸發(fā)動(dòng)作,現(xiàn)狀和次狀信息。

        

      ?

      4、外部狀態(tài)存儲(chǔ)


        有時(shí)候,當(dāng)前對(duì)象的狀態(tài)需要來(lái)自于一個(gè)ORM對(duì)象,或者需要將當(dāng)前對(duì)象的狀態(tài)保存到一個(gè)ORM對(duì)象中,UI框架需要存儲(chǔ)一個(gè)狀態(tài)到綁定屬性中。為了支持這種外部狀態(tài)存儲(chǔ),StateMachine類(lèi)的構(gòu)造函數(shù)支持了讀寫(xiě)狀態(tài)值。如代碼里,通過(guò)使用myState可以去存儲(chǔ)和獲取狀態(tài)值。
      var stateMachine = new StateMachine<State, Trigger>( () => myState.Value, s =>
      myState.Value = s );
      ?

      5、內(nèi)省


        該狀態(tài)機(jī)可以通過(guò)StateMachine.PermittedTriggers屬性獲取當(dāng)前狀態(tài)下可以觸發(fā)的觸發(fā)器列表。并能夠使用StateMachine.GetInfo()獲取狀態(tài)相關(guān)的配置信息。
      public IEnumerable<TTrigger> PermittedTriggers { get { return
      GetPermittedTriggers(); } }//返回StateMachineInfo對(duì)象,包含狀態(tài)及觸發(fā)器列表。
      _machine.GetInfo();
      ?

      6、衛(wèi)語(yǔ)句


        狀態(tài)機(jī)將根據(jù)衛(wèi)語(yǔ)句在多條轉(zhuǎn)換線路之間進(jìn)行選擇,衛(wèi)語(yǔ)句必須是互斥的,多個(gè)衛(wèi)語(yǔ)句不能同時(shí)生效。子狀態(tài)可以通過(guò)重新指定來(lái)覆蓋狀態(tài)轉(zhuǎn)換,但是子狀態(tài)不能覆蓋父狀態(tài)允許的狀態(tài)轉(zhuǎn)換,當(dāng)觸發(fā)器觸發(fā)時(shí),衛(wèi)語(yǔ)句開(kāi)始評(píng)估線路選擇,因此不會(huì)帶來(lái)其它方面的影響。
      phoneCall.Configure(State.OffHook) .PermitIf(Trigger.CallDialled,
      State.Ringing, ()=> IsValidNumber) .PermitIf(Trigger.CallDialled,
      State.Beeping, ()=> !IsValidNumber)
      ?

      7、參數(shù)化觸發(fā)器

        支持將強(qiáng)類(lèi)型參數(shù)提供給觸發(fā)器,使用方法PermitDynamic()配置狀態(tài)機(jī)時(shí),能夠通過(guò)觸發(fā)器參數(shù)動(dòng)態(tài)選擇目標(biāo)狀態(tài)。
      var assignTrigger = stateMachine.SetTriggerParameters<string>(Trigger.Assign);
      stateMachine.Configure(State.Assigned) .OnEntryFrom(assignTrigger, email=>
      OnAssigned(email)); stateMachine.Fire(assignTrigger,"[email protected]");
      ?

      8、忽視轉(zhuǎn)換和重入狀態(tài)

        如果觸發(fā)了一個(gè)沒(méi)有配置過(guò)的線路,將會(huì)拋出一個(gè)異常,通過(guò)使用Ignore方法,忽視一些觸發(fā),當(dāng)觸發(fā)了此類(lèi)觸發(fā)器時(shí),不會(huì)拋出異常,而改為忽略該次觸發(fā)。
      phoneCall.Configure(State.Connected) .Ignore(Trigger.CallDialled);
        另外,一個(gè)狀態(tài)能夠使用PermitReentry方法配置為重復(fù)進(jìn)入(從本狀態(tài)到本狀態(tài)),entry和exit事件也會(huì)被再次觸發(fā)。
      stateMachine.Configure(State.Assigned) .PermitReentry(Trigger.Assigned)
      .OnEntry(()=> SendEmailToAssignee());
        默認(rèn)情形下,必須明確忽略哪些觸發(fā)器。 當(dāng)未配置的觸發(fā)器被觸發(fā)時(shí)默認(rèn)是拋出異常,可以通過(guò)使用OnUnhandledTrigger配置狀態(tài)機(jī)覆寫(xiě)處理異常情形。
      stateMachine.OnUnhandledTrigger((state, trigger) => { });
      ?

      9、導(dǎo)出DOT格式圖

        運(yùn)行狀態(tài)可視化狀態(tài)機(jī)是很有用處的,使用狀態(tài)機(jī)時(shí),代碼是命令式的,而狀態(tài)圖是副產(chǎn)物。
      phoneCall.Configure(State.OffHook) .PermitIf(Trigger.CallDialled,
      State.Ringing, IsValidNumber);string graph =
      UmlDotGraph.Format(phoneCall.GetInfo());
        UmlDotGraph.Format()方法返回代表狀態(tài)機(jī)的字符串,使用DOT graph語(yǔ)言格式。這個(gè)可以被支持DOT graph語(yǔ)言的工具渲染。像
      graphviz.org <http://www.graphviz.org/>和viz.js
      <https://github.com/mdaines/viz.js>的dot command line
      <http://www.graphviz.org/doc/info/command.html>工具。

        諸如生成的字符串在viz.js <https://github.com/mdaines/viz.js>中解析的狀態(tài)機(jī)圖形。

        

      ?

      10、異步觸發(fā)


        該狀態(tài)機(jī)支持異步操作,對(duì)于Entry/Exit方法等都有相應(yīng)的異步方法,帶Async結(jié)尾,并且對(duì)于觸發(fā)也有異步方法FireAsync(),需要注意的是,盡管使用了異步,但仍然是單線程操作,不能被多個(gè)線程同時(shí)使用。
      stateMachine.Configure(State.Assigned) .OnEntryAsync(async () => await
      SendEmailToAssignee());await stateMachine.FireAsync(Trigger.Assigned);
       至此,對(duì)于狀態(tài)機(jī)Stateless的功能差不多了解完畢了,開(kāi)始將狀態(tài)機(jī)融入到項(xiàng)目中實(shí)際使用起來(lái),也已經(jīng)加入到日程中。

      ?
      2019-09-22,望技術(shù)有成后能回來(lái)看見(jiàn)自己的腳步

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問(wèn)題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          色www亚洲国产张柏芝 | 尻屄视频在线播放 | 草草偷拍视频 | 女性裸体不遮胸平台 | 一级特黄60分钟免费看 | 亚洲japanese制服美女 | 婷婷成人AV | 欧洲无人区卡一卡二卡三 | 毛片乱伦 | 18禁黄网站网址免费入口 |