ステートマシンの実装方法について少し混乱しています。
一部の州が同じアクションを共有しているため、階層的であることはすでに知っています。
私はこれらのパラメータによって何をする必要があるかを決定します:
- クラス(値は次のとおりです:Base、Derived、Specific)
- OpCode
- パラメータ1-オプション
- パラメータ2-オプション
私の階層はクラスによって決定され、OpCodeはアクションを表します。
DerivedはBaseのOpCodeを使用でき、SpecificはBaseとDerivedの両方のOpCodeを使用できます。
素朴な実装は次のとおりです。
void (*const state_table [MAX_CLASSES][MAX_OPCODES]) (state *) {
{base_state1, base_state2, NULL, NULL},
{base_state1, base_state2, derived_state1, NULL},
{base_state1,base_state2, derived_state1, specific_state3},
};
void dispatch(state *s)
{
if (state_table[s->Class][s->OpCode] != NULL)
state_table[s->Class][s->OpCode](s);
}
これにより、メンテナンスが非常に迅速になります。
状態をスーパークラスにマップする別の方法はありますか?
編集:さらに計算すると、すべてではないに
してもほとんどのOpCodeを使用するだろうと思うようになりますが、使用可能なすべてのクラスを使用するわけではありません。
別の説明:
一部のOpCodeは、複数の派生クラスと基本クラスを介して共有される場合があります。
例えば:
- 基本クラス であるAnyというクラスがあります。オペコードがあり ます:STATE_ON、STATE_OFF、STATE_SET。
派生クラスであるMyGroupという 別のクラスがあります。オペコードがあります: STATE_FLIP、STATE_FLOP。
3番目のクラスは、OpCode: STATE_FLIP_FLOP_AND_FLOOPを持つThingInMyGroupと 呼ばれる特定のクラスです。
したがって、クラスAnyのメッセージがサーバーから送信され、すべてのクライアントで受信されて処理されます。
クラスMyGroupのメッセージはサーバーから送信され、すべてのクライアントで受信され、 MyGroupに属するクライアントでのみ処理されます。Anyクラスに有効なすべてのOpCodeは、 MyGroupクラスに有効です。
クラスThingInMyGroupのメッセージはサーバーから送信され、すべてのクライアントで受信され、 MyGroupに属し、ThingInMyGroup*であるクライアントでのみ処理されます。AnyクラスおよびMyGroupクラスに有効な**OpCodesはThingInMyGroupクラスに有効です。 。
メッセージが受信された後、クライアントはそれに応じてACK/NACKを実行します。
スイッチケースやconst配列は大きくなると保守できなくなるため、使用しない方がいいです。
次のような柔軟な設計が必要です。
- 各クラスで使用可能なOpCodeを指定します。
- 各クラスのスーパークラスを指定し、その指定を通じて、現在のOpCodeで表される関数ポインターを呼び出せるようにします。