質問

FSM(編集:有限状態マシン)状態をどのように実装しますか?私は通常、一連の関数、ディスパッチャー、現在の実行状態を示すスレッドのようなFSMについて考えます。つまり、私は状態を表す機能/ファンサーへの呼び出しをブロックします。

ちょうど今私は別のスタイルで1つを実装しました。ここでは、機能(オブジェクト)を持つ状態をまだ表していますが、スレッドはただ state->step() 方法。できるだけ早く戻そうとします。状態が終了し、移行が行われるべき場合、それはそれに応じてそれを示します。機能はほとんどのように見えるので、私はこれを「ポーリング」スタイルと呼びます。

void step()
{
  if(!HaveReachedGoal)
  {
    doWhateverNecessary();
    return; // get out as fast as possible
  }
  // ... test perhaps some more subgoals
  indicateTransition();
}

FSM内のFSMであることを知っています。

かなり単純な感じがしますが、特定の利点があります。スレッドがブロックされている、またはある種のものに保持されている間while (!CanGoForward)checkGoForward();ループは面倒で扱いにくい場合がありますが、投票はデバッグがはるかに簡単に感じられました。それは FSM オブジェクトはステップごとにコントロールを取り戻し、デバッグ情報を出すのは簡単です。

まあ私は私の質問から逸脱しています:どうやって FSMの状態を実装しますか?

役に立ちましたか?

解決

州の設計パターンは、FSMを実装する興味深い方法です。

http://en.wikipedia.org/wiki/state_pattern

FSMを実装する非常にクリーンな方法ですが、FSMの複雑さに応じて乱雑になる可能性があります(ただし、状態の量ではありません)。ただし、利点は次のとおりです。

  • コードの複製を排除します(特に/elseステートメントの場合)
  • 新しい州で拡張する方が簡単です
  • クラスはより良い結束力があるため、関連するすべてのロジックは1つの場所にあります。これにより、コードがテストを簡単に書くことができます。

このサイトにはJavaおよびC ++の実装があります。

http://www.vincehuston.org/dp/state.html

他のヒント

私がFSMSを実装するフライングスパゲッティモンスターのスタイル(FSMスタイルFSMS)と呼ばれるものが常にあります:ロッサを使用してください gotos。例えば:

state1:
  do_something();
  goto state2;

state2:
  if (condition) goto state1;
  else           goto state3;

state3:
  accept;

とても素敵なスパゲッティコード:-)

私はそれをテーブルとして、メモリ内のフラット配列、各セルは状態です。 CVSソースをご覧ください 放棄されたDFAプロジェクト. 。にとって :

class DFA {
    DFA();
    DFA(int mychar_groups,int mycharmap[256],int myi_state);
    ~DFA();
    void add_trans(unsigned int from,char sym,unsigned int to);
    void add_trans(unsigned int from,unsigned int symn,unsigned int to);
    /*adds a transition between state from to state to*/
    int add_state(bool accepting=false);
    int to(int state, int symn);
    int to(int state, char sym);
    void set_char(char used_chars[],int);
    void set_char(set<char> char_set);
    vector<int > table; /*contains the table of the dfa itself*/
    void normalize();

    vector<unsigned int> char_map;
    unsigned int char_groups; /*number of characters the DFA uses,
                    char_groups=0 means 1 character group is used*/
    unsigned int i_state; /*initial state of the DFA*/
    void switch_table_state(int first,int sec);
    unsigned int num_states;
    set<int > accepting_states;
};

しかし、これは非常に具体的なニーズのためでした(正規表現の一致)

最初のFSMプログラムを覚えています。私は非常にシンプルでCでそれを書きました スイッチ 声明。ある状態から別の状態に切り替えるか、次の状態に切り替えることは自然に思えました。

それから私はaを使用するために進みました テーブルルックアップアプローチ. 。このアプローチを使用して、非常に一般的なコーディングスタイルを書くことができました。しかし、要件が変更されたときに数回捕まったので、いくつかの追加のイベントをサポートする必要があります。

私は最近FSMを書いていません。私が書いた最後のものは、私が使用したC ++のCommsモジュールのためでした」状態設計パターン「Aと一緒に」コマンドパターン" (アクション)。

複雑な状態マシンを作成している場合は、チェックアウトすることをお勧めします SMC - ステートマシンコンパイラ。これにより、ステートマシンのテキスト表現が必要になり、お好みの言語にまとめられます。これは、Java、C、C ++、C#、Python、Ruby、Scalaなどをサポートしています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top