ステート マシンは動作中の状態パターンにすぎないのでしょうか、それとも実際にはこれら 2 つに違いがあるのでしょうか。
「ステート デザイン パターン vs ステート マシン」という太字のタイトルのこの記事を見つけましたが、結局のところ、彼はステート パターンがステート マシンを時代遅れにするだけであり、ステート マシンと比較してステート マシンとは何かを正確に説明していません。状態パターンの実装。
ステート マシンは動作中の状態パターンにすぎないのでしょうか、それとも実際にはこれら 2 つに違いがあるのでしょうか。
「ステート デザイン パターン vs ステート マシン」という太字のタイトルのこの記事を見つけましたが、結局のところ、彼はステート パターンがステート マシンを時代遅れにするだけであり、ステート マシンと比較してステート マシンとは何かを正確に説明していません。状態パターンの実装。
私が同僚にこの違いを説明する方法は、ステート マシンがよりモノリシックであるのに対し、ステート パターンは多くのスタンドアロンのカプセル化されたステートのより分散化された実装であるということです。ステート マシンのモノリシックな性質は、単一のステートを別のマシンで再利用するのが難しく、ステート マシンを複数のコンパイル ユニットに分割するのが難しいことを意味します。一方、このモノリシック設計により、ステート マシンの最適化が大幅に向上し、多くの実装ですべての遷移情報をテーブル内の 1 か所で表すことができます。これは、ステート マシンのアーキテクチャまたは機能の責任者が、実装されているプログラミング言語に精通していない場合に特に適しています。多くのエンジニアリングと数学の専攻者は、ステート マシンについては学んでいますが、プログラミング分野の教育はほとんどまたはまったく受けていないことを思い出してください。これらのタイプの人々に、状態パターンのページとページよりも遷移、アクション、およびガードの表を提示する方がはるかに簡単です。
この記事は実際には良い読み物でしたが、私はいくつかの点で著者に同意しません:
状態の切り替えには割り当てが必要であることに注意してください。これはスピードを殺します。これは、キャッシュ ミスを 1 つまたは 2 つ節約するために、バッファー内のすべての状態を隣り合わせに配置することで解決できます。ただし、これには Authors の例に大きな変更が必要になります。
また、処理されないイベントは、静的ステート マシンのようにインライン化および最適化して取り除くことができないことに注意してください。これは、状態パターンにより、イベントが動的な間接化のレイヤーの背後にあるためです。これは、要件によっては効率を損なう可能性もあります。
メンテナンスの観点から、未処理のイベントのログ記録は、状態パターンを持つ 1 つの中央スーパーステートから実行できないことに注意してください。また、新しいイベント タイプ/ハンドラー関数を追加するには、すべての状態に関数を追加する必要があります。私はそれがメンテナンスフレンドリーだとは思わない。
また、すべての状態の内部の仕組みを見るよりも、すべての遷移をテーブルで見る方が好きです。著者は、状態を追加する方が簡単であるということは正しいですが、非常に最小限でしかありません。たとえば、ブースト ステートチャートを使用すると、状態をその親と子の状態のリストに追加するだけで済みます。これが唯一の違いです。
速度が問題ではなく、ステート マシンの階層がフラットなままである可能性が高い場合に、ステート パターンを使用します。著者は、最初の実装は通常、ステート マシンに比べてステート パターンを使用したほうが簡単であり、一般に、より多くのプログラマがより多くのステート マシンを使用する必要があることは正しいです。
ステート パターンの引数の 1 つは、ライブラリでステート マシンを定義し、ユーザーが拡張できる「オープン クローズド」ステート マシンの実装を可能にすることです。主流のステート マシンで知る限り、これは不可能です。フレームワーク。
ステート マシンは、いくつかの方法で設計および実装できます。1 つの方法は、Gang of Four の本に記載されている状態パターンを使用することです。ただし、ステート マシンを実装するパターンは他にもあります。
たとえば、Miro Samek の研究については、『Practical UML statecharts in C/C++, 2nd ed. (組み込みシステムのためのイベント駆動型プログラミング)
この質問も興味深いかもしれません。