ゆにっとさん、それは趣味に走りすぎなのでは...
あ、はいすみません、よく知られたパターンなので遊んでしまいました。ストラテジーってネーミングがもうね...
Strategy パターンは GoF のデザインパターンの中でもっともわかりやすく、多用されるパターンです。オブジェクトから、ある特定部分の判断を行うアルゴリズムを分離し、それを別のオブジェクトに持たせて、has-a 関係で委譲してやる形です。
アルゴリズムを分離することには、3 つのメリットがあります。
ひとつは、言わずもがな「関心の分離」です。この部隊の戦力をもってすれば、どんな強大な敵も撃退できるのだ。けど、部隊の最前線は目の前の戦闘にしか集中できません。なので、大極を見た戦略判断は司令部に担ってもらうのです。SOLID の単一責任原則 (SPR: オブジェクトの責務はひとつ) です。
もうひとつは、if
の排除です。すべての作戦に関する知識を持っていて、いまどの作戦行動中なのかを考慮する if
文を大量に抱えていること自体が、すでに部隊の集中力を阻害する余計な関心事です。なので、前線の兵士にはなるべく考えないようにさせ、判断を委譲する先をひとつ決めて、「伊作戦」なのか「呂作戦」なのか、はたまた次の作戦なのか、司令部への報告に対する応答戦術指令が適宜変わるようにするのです。
最後のメリットは、カンのいい人はもうわかっていると思いますが、この部隊は作戦さえ立案すればどんな行動でも取れるということ、つまり、オブジェクトの追加によっていくらでも拡張可能だということです。作戦が増えるたびに部隊を再訓練していては、臨戦態勢を維持できませんね。単純な追加によって挙動を拡張可能... これはまぎれもなく開放閉鎖原則 (OCP: 拡張に対してオープンに、変更に対してクローズであれ) です。
Strategy パターンにおいて重要なのは、戦力の主体はあくまで前線であることと、作戦を与えるのが司令官だということです。
防衛戦では作戦行動のイニシアチブが敵側にあるので、前線は独自の判断で応戦を開始ないといけません。司令部がいちいち Command を発行して動かしていては間に合わないので。Command はいちど実行すれば無効になって、次を待たないとだめですが、Strategy は切り変わるまでずっと存続し、何度もコール可能です。
また、部隊の各小隊が、自部隊の戦局 State が変わったからと勝手に作戦を変更したら大変です。映画とかでも、そういうのはたいがい死亡フラグですね。State の具象はたいてい、同一パッケージではなく外部にあり、自力で new
できなくて、セッターなどで与えられるものなのです。
具体例がなくてわかりにくい? コンフィグでどのデータベースドライバを選ぶかで、JDBC や PDO の通信内容は変わりますよ、これでいいですか。外部から択一で与えられて、変更しないかぎり同じドライバが使われ続け、新たにデータベースエンジンが増えればドライバを追加で増やせる。はい、そういうやつです。ね、あるあるすぎでしょ。