LoginSignup
32
16

More than 3 years have passed since last update.

マンガでわかる State

Last updated at Posted at 2019-12-20

C7F520A9-34CA-44D2-A407-B07B4CD6120B.png

女の子はフクザツなので Q と聞いたらどんな A が出てくるかわからない、ってのがそけっとさんの言い分です。なるほど、CPU 負荷が高いのかメモリが枯渇しているのか、はたまたエラーによる例外フローが頻発して調子悪いのか... すべての組み合わせで可能性を考慮しないといけない。うーんなるほど。なるほど??

まあそういうことにしときましょうか。でもね、ソフトウェアのモデリングではとなると話は別ですからね。情報の複雑さはどんな理由があろうとも敵でしかありません。かわいいからって許しちゃダメです。

State パターンは、オブジェクトの内部に状態変化モデルを持たせるパターンです。それで、あらゆる可能性への配慮だとかいう、いつエンバグするかわからないような複雑なロジックを廃止して、今の状態は何か、その状態における振る舞いはこうだ、と一意に決めようという発想です。

めもりーちゃんは State パターンを導入したのでとてもシンプルです。やる気の決定は各 State オブジェクトのメソッドに持たせ、親となるオブジェクトはなにも考えず、ロジックを委譲するだけにします。

状態を表すのは具象状態クラスのインスタンスです。主オブジェクトには現在の状態をあらわす State 抽象型のポインタがひとつあります。そして、状態数と同じコンクリートクラスを実装し、ポインタがそのいずれかを指すようにします。状況変化に応じて、ポインタが指す State のインスタンスが変化していけば、振る舞いが変わります。

アルゴリズムを持つオブジェクトのインスタンスという意味では、Command パターンや Strategy パターンと似ています。この場合もやはり、クラス図の主要な箇所に着目すれば、抽象のメソッドコールを派生クラスで具象化するという点で、見分けがつかないでしょう。

State パターンで重要なのは、複数の委譲先インスタンスの切り替わりが、自律的に起きるということです。Command の実行者は、生成した者を知りませんし、切り替わりも起きません。Strategy の場合、アルゴリズムを与えるのは自分ではなく、より上の権限を持つ他者です。

それらに対して State は、自己の内部で委譲先を管理し、ステートマシンによってそれらが勝手に切り替わります。外部のオブジェクトに State の存在を知らせる必要はありません。というより、知ってしまうともはやカプセル化にならなくなってしまうのでダメです。

めもりーちゃんがやる気を出すかどうかは、他者が決めることではなくて、眠さや燃え尽き虚無感、ゲーセン行きたさで決まります。それは、直前状態と遷移トリガーによって、内部のステートマシンが決定するのです。

ゲームプログラミングでなら、キャラクターのモードがどう切り替わるか、切り替わったモードで何ができるのかをモデリングするでしょう。ビジネス用途のアプリケーションでも、そのアプリケーションが扱う情報がいまワークフローのどの段階にあるかで、誰が何をアクションできるかは変わってきます。

純粋関数型の発想と異なり、オブジェクト指向では、モノの内部状態の変化を許容して単純化するほうがわかりやすい場合は、躊躇なくそれを選びます。が、そのような選択をしたとしても、状態が多次元な変化を起こすのはやはり複雑化 (ときには2つの状態が矛盾するような場合も) を招きます。

わかりやすい例でいえば、アクティベート前のユーザーアカウントに、退会フラグが立ったとき、その人ははどういう状態なのでしょう? みたいなの、経験ないですか。

よくよく考えれば、複数のフラグが直交関係になくて、その組み合わせは一意なステートを表している、というとき、ステートグラフで考えれば、余計な心配を忘れてモデリングに集中できますよね。

32
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
16