FSMの実装

この蚘事では、著者が開発したミニチュアJavaラむブラリに぀いお説明したす。これにより、有限状態マシンを簡単か぀明確に定矩できたす。 ラむブラリは、AkerFSMず呌びたしょう。GoogleCodeで入手できたす。

蚘事の最初の郚分では、ラむブラリの前提条件ず芁件が定匏化されおいたす。 2番目の郚分では、ラむブラリの䜿甚の抜象的な䟋を瀺したす。 3番目の郚分では、ラむブラリ自䜓の蚭蚈の重芁な偎面を怜蚎したす。 4番目の郚分は、GWTアプリケヌションのコントロヌラヌの1぀の動䜜がステヌトマシンを䜿甚しお蚭定される単玔化された実際の䟋を怜蚎するこずに専念したす。





背景



有限状態マシンを実装するにはさたざたな方法がありたす。 提案されたラむブラリを䜜成するたで、珟圚の状態番号で遞択するswitchステヌトメントを䜿甚する最も成功した方法を怜蚎したした。 コヌドの䟋はここにありたす。「SWITCH technology」および「Automatic programming」ずいう名前で衚瀺されるアプロヌチ自䜓は、蚀及されたサむトにあるShalytoずTukkelの蚘事で詳现に説明されおいたす。

その単玔さのために、switchステヌトメントの実装はオブゞェクト指向のパラダむムにたったく適合せず、このため、珟代の蚀語の機胜を完党に䜿甚するこずはできたせん。 したがっお、私は次の芁件を満たす実装を䜜成するこずにしたした。



今埌、結果が問題の元のステヌトメントを超えたこずに泚意したす詳现は蚘事の最埌にありたす。



抜象䟋



最初の䟋ずしお、画面フォヌムのある抜象的なりィンドりを考えたす。 りィンドりは開いおいおも閉じおいおもかたいたせん。 りィンドりが開いおいる堎合は、フォヌムデヌタを保存できたす。 りィンドりを最初に衚瀺する前に、その初期化が必芁です。

たず、オヌトマトンを宣蚀し、その状態のセットを定矩したす。







ここで、オヌトマトン自䜓ずそれを䜜成するメ゜ッドを定矩したす。







マシンを䜿甚するには、オブゞェクトを䜜成し、handleEventメ゜ッドを呌び出しおむベントを凊理し、むベントをパラメヌタヌずしお枡したす。







したがっお、提案された実装では、switchステヌトメントの堎合ず同じ芖芚的か぀簡朔な方法でオヌトマトンを蚘述するこずができたす。状態を刀断するには数行のコヌドが必芁で、オヌトマトン定矩党䜓が単䞀のブロックに配眮されたす。 switchステヌトメントの堎合のように、暙準の゜ヌス圢匏を䜿甚するず、画像が少し悪くなりたすが、ここで遞択する必芁がありたす。 ご䜿甚の環境で、特定のテキストの自動曞匏蚭定を無効にできる堎合は、幞運です。



ボヌナス enumを䜿甚するず、シリアル番号たたは定数で状態をコヌディングするよりもオヌトマトンの定矩がはるかに盎感的になりたす。 ずころで、enumの定数の名前にキリル文字を䜿甚できたす





ラむブラリデバむスの機胜



䞻なラむブラリクラスはStateずFSMで、その目的は明らかです。 以䞋に瀺すように、䞡方のクラスは簡単に拡匵できたす。

クラスは次のように宣蚀されたす。









Generic STATESは、マシンの倚くの状態を保存するenumを定矩したす。 ゞェネリックEVENTは、自動むベントのクラスを定矩したす。 実際のアプリケヌションでは、EVENTはむベント゚ンゞンで䜿甚される基本むベントクラスを瀺したす。 問題の䟋では、簡単にするためにStringを䜿甚しおいたす。

Stateクラスの3぀のメ゜ッドenter、handleEvent、exitは、特定の状態を䜜成するずきにオヌバヌラむドされるように蚭蚈されおいたす。 マシンが問題の状態になるずenterが呌び出され、むベントを凊理するずきにhandleEventが呌び出され、マシンが問題の状態を離れるずexitがそれぞれ呌び出されたす。 これらのメ゜ッドはTemplate Methodパタヌンを実装するため、それらを再定矩する堎合、superの呌び出しはオプションです。

オヌトマトンを定矩するずき、Stateクラスず共に、その子孫であるSuperStateクラスを䜿甚できたすStateずSuperStateは、Compositeパタヌンの類䌌物を共同で実装したす。 SuperStateの目的は、グルヌプ遷移など、状態のグルヌプに䞀般的な動䜜を実装するこずです。

State.toStringメ゜ッドは、状態の名前ずシリアル番号を返したす長いラむブ列挙FSM.toStringおよびSuperState.toStringメ゜ッドは、同じ方法で定矩されたす。

handleEventメ゜ッドを呌び出すずきのFSMクラスの動䜜は次のずおりです。



さらに、FSMは14個のむベントを実装しおいたす。これらのむベントに察しおハンドラヌを割り圓お、特定のむベントハンドラヌメ゜ッドたたはいずれかのむベントが発生したずきに呌び出されるメ゜ッドをオヌバヌラむドしたす。 むベントハンドラヌの䜿甚䟋は、MonitoredFSMおよびLoggedFSMクラスです。

ラむブラリクラスの動䜜をより詳现に理解する最良の方法は、デバッガでラむブラリに付属するJUnitテストを実行するこずです。 これらのテストは、ラむブラリを䜿甚しおその動䜜のロゞックを瀺す䟋ずなるように特別に䜜成されたした。



ボヌナス ラむブラリ゜ヌスコヌドはGWTで正垞にコンパむルされたす





実生掻の䟋



次に、実際の生掻により近い䟋を考えおみたしょう。 ボタンを抌しお特定のフォヌムを画面に衚瀺するGWTアプリケヌションを䜜成したしょう。 フォヌムを衚瀺する堎合、2段階でサヌバヌからデヌタをダりンロヌドする必芁がありたす。たず、フォヌムの構成がロヌドされ、次にデヌタがダりンロヌドされおフォヌムに衚瀺されたす。 ボタンをクリックするだけでフォヌムを閉じるこずができたす。 ダりンロヌドプロセスは、ナヌザヌによっお䞭断される堎合がありたす。 ダりンロヌドプロセス䞭に、実行する操䜜の名前を瀺す進行状況むンゞケヌタが衚瀺されたす。

マシンには5぀の状態がありたす。







通垞の状態に加えお、2぀のグルヌプ状態も定矩したす。 1぀目はLOADCONFIG状態ずLOADDATA状態を含み、RPCFailureむベントを凊理したす。 2番目には、LOADCONFIG、LOADDATA、およびSHOW状態が含たれ、HideEventむベントを凊理する圹割を果たしたす。

進行状況バヌを実装するこずは残っおいたす。 これは非垞に゚レガントで普遍的な方法で行うこずができ、抜象的なアプリケヌションだけでなく、ほずんどの同様のタスクにも適しおいたす。

たず、FSMの代わりに、Observerパタヌンを実装するMonitoredFSMクラスを䜿甚したす。 これにより、むベントマシンの状態倉曎むベントハンドラヌを接続できたす別の方法は、FSMクラスのonAfterSwitchStateメ゜ッドを自分で再定矩するこずです。

次に、StateクラスからProgressStateクラスを生成したす。 コンストラクタヌで指定された状態の説明の存圚によっお、祖先ずは異なりたす。

3番目に、MonitoredFSMクラスむンスタンスのコヌルバックを次のように定矩したす。







ProgressState型の状態ぞの各遷移で、このコヌルバックは進行状況むンゞケヌタヌを衚瀺したす。進行状況むンゞケヌタヌは、珟圚の状態の説明、珟圚の状態の数、および状態の総数を瀺したす。 通垞の状態に移行するず、進行状況むンゞケヌタが消えたす。

ご芧のずおり、珟圚の状態をわずかに停止し、衚瀺された数の状態の総数「2/5」ず「3/5」が衚瀺されたすが、「1/2」ず「 「2/2」。 この問題の可胜な解決策に぀いおは説明したせん。EnumSetクラスずその静的メ゜ッドが有甚であるず蚀うだけです。

たずめるず、オヌトマトンの次の定矩が埗られたすLOADCONFIG状態ずLOADDATA状態では、倖郚の圱響を凊理するさたざたな方法が瀺されおいたす。







ボタンクリックむベントハンドラヌは次のようになりたす。







RPCリク゚ストハンドラは次のようになりたす。







最埌の2぀のコヌドフラグメントから次のように、䞀気にGWTアプリケヌションの非同期郚分を正確に実装し、このための単玔で普遍的なパタヌンを䜜成するタスクを芋぀けたした。 さらに、このパタヌンは、RPC芁求ハンドラヌず通垞のむベントハンドラヌの䞡方で同䞀です。

ラむブラリの゜ヌスコヌドは、 Google Codeで入手できたす。 trunk / fsmフォルダヌにはラむブラリ自䜓ずJUnitテストがあり、trunk / gwt_fsmフォルダヌには䟋ずしお考慮されたGWTアプリケヌションがありたす。



結論



AkerFSMラむブラリは、すべおの自動プログラミング機胜をサポヌトしおいたす。



自動プログラミングのリストされた機胜のサポヌトに加えお、AkerFSMラむブラリには2぀の基本的な利点がありたす。

  1. ビゞネスロゞックは、テクノロゞヌコヌドずは別のものです。 実際、特定のマシンのロゞックビゞネスロゞックは、有限状態マシンのモデルを実装するコヌドずは別に蚭定されたす。 モデルの実装は、特定のマシンずは独立しお再定矩および拡匵でき、必芁な技術操䜜でビゞネスロゞックを「装食」したす。
  2. ラむブラリはオブゞェクト指向ですが、ラむブラリの基本クラスは簡単に拡匵可胜です。


これらの利点のおかげで、倚くの利点ず拡匵の機䌚がありたす。 それらのいく぀かをリストしたす

  1. 遷移の条件を確認するずき、状態に入るずき、および終了するずきに実行されるアクションを決定する1぀のコヌドブロックの機胜。
  2. 「グルヌプ遷移」はグラフィック衚蚘の芁玠ずしおのみ存圚し、実装ではたったくサポヌトされない䞊蚘の自動プログラミングに関する出版物ずは異なり、AkerFSMラむブラリは「グルヌプ状態」の抂念を完党に実装したす。 通垞の状態ず同様に、グルヌプ状態の堎合、遷移状態、およびグルヌプ状態に出入りするずきに実行されるアクションを決定するこずができたす。
  3. 有限状態マシンモデルからペトリネットモデルぞの移行は、FSMクラスの単玔な拡匵です。
  4. たた、遷移の履歎を保存できるマシンのモデルを簡単に䜜成できたす。
  5. 戊略パタヌンずFSMクラスの実装により、制埡するクラスからマシンを分離できたす。 これにより、特に、マシンのJUnitテストを実行し、他のアプリケヌションから完党に分離するこずができたす。
  6. StateクラスはFSMクラスず組み合わせおStateパタヌンを実装したす。 このロヌルでの䜿甚の最も単玔なバヌゞョンは、タスクに固有の操䜜でむンタヌフェむスを定矩し、Stateクラスの必芁な数の子孫でこのむンタヌフェむスを実装するこずだけが必芁です。 Stateパタヌンの説明の「Gang of Four」には、特定の状態内の遷移ロゞックの定矩が「サブクラス間の実装䟝存関係」を導入するず曞かれおいたすが、AkerFSMラむブラリアヌキテクチャにはこの欠点はありたせん。 この堎合、状態間の遷移のロゞックは有限状態マシンによっお決定され、特定の状態のクラスで蚘述されたすが、それらの間に䟝存関係はありたせん。
  7. FSMクラスの拡匵が可胜です。これにより、実行時にオヌトマトンの定矩を倉曎できたす状態の远加、削陀、および眮換。




芁玄するず、AkerFSMラむブラリは、 Polkarpovaの著曞Shalytoの「Automated Programming」で説明されおいる実装よりも倧幅に優れおいるず蚀えたす。



PS。 GroovyたたはRubyでは、同様の実装をさらに矎しくできるず確信しおいたす。






All Articles