著作一覧 |
ストラテジパターンを実装していく場合のキモっていうのは、どのストラテジを適用するかの判定にあると仮定する。もし、判定しないとすれば、すべてのストラテジに順にコンテキストを与えていくことが可能となり(ストラテジはコンテキストを見て処理を適用するかどうかを決定する)、それはチェインオフレスポンサビリティになってしまうから?
多分、それは違うだろう。ストラテジはコンテキストが持つデータを変更する可能性があるが、チェインオフレスポンサビリティはクライアントが持つデータを変更しないはずだ。もし変更すれば、それは順序依存性を持つことになる。しかしレスポンサビリティの呼び出し順序に依存しないように実装しなければ、レスポンサビリティがチェインのどの位置に置かれるかによって動作が変わることになり元の意味が変わってしまう。
ストラテジがあらかじめすべてインスタンス化されている状況、たとえばシングルトンとして実装できる場合、すなわちステートを持たない(インスタンス変数は実行時には不変な場合)ように実装していれば、コンテキストが保持する外部データをビジターとしてすべてのストラテジをビジットしても良いのではないか? 順序依存性を意識してストラテジを階層化(単なる配列でも良いかも)しておくか、あるいはビジター自体は単なる入力データでストラテジによって変更されないと仮定すれば。(追記:イベントモデルとして考えろ、と言われたのを思い出した。オブザーバーとしてストラテジを配置ということだ。チェインオブレスポンサビリティは、「誰か(多分1つのオブジェクト)が処理して終結」で、ここで書いているのは「処理したいやつはやってくれ(複数オブジェクトを前提)」だから元から間違っていることになる)
ステートとストラテジは似ていると言われるが、片方は明示的な順序依存性を持ち基本的にはすべてのステートが適用される可能性を持つのに対し、ストラテジの各オブジェクトは互いに関連しない(したがって順序依存性は本来持たない)という大きな違いがある。だから、こちらについては疑問はないのだが、さてきれいにストラテジを適用するように作ろうとすると、ビジターかチェインオブレスポンサビリティのように実装するのが良いように感じることが多い。処理すべきかどうかの判定もストラテジに任せたいし、逆にコンテキストの外部データ(つまるところトランザクションだ)からはビジットさせたいからだ。
追記:ステートの各オブジェクトは少なくても次のステートを知っている。でも、ストラテジは(「次」というものも本当は無いはず)互いに関係をもたない(持つのなら、ストラテジをコンポジションしたストラテジとしたほうが良いのでは)。
かくして、このあたりは明確にこうだとはいえないものとなる。アルゴリズムの適用についてはストラテジ、処理の適用はトランザクションがビジターとしてストラテジを巡っていくかまたは(順序依存性を認めた)チェインオブレスポンサビリティとしてストラテジをブートストラップ(この場合はそんな感じだ)していくとか。(追記:チェインオブレスポンサビリティではなく、オブザーバーとして考えればブートストラップもへったくれも無い―順序依存性が無い前提)
というあたりで、実際他の人はどんなふうにしてんのかなぁ、と考えてみたり。
追記:Saisseさんの指摘を含めて幾つか追記(確かにテンプレートメソッドパターンのメソッドをオブジェクト化したものですね。そういう発想は無かった――それこそ粒度ってことだけど――けど、納得はいきます)。実際には微妙に順序依存性があり、かついくつかは独立、かついくつかは途中で打ち切りあり(単純なオブザーバーとも違う)とか、いろいろです。チェインオブレスポンサビリティとオブザーバーのように、ここでも僕がビジターパターンという言葉を誤用して(少なくてもストラテジが単純に並存しているのなら全然ビジターが回遊していく対象では無いので、ビジターパターンという言葉が表す要素群とは異なる)、本来イテレータと呼ぶべきものについてそう言っているのでしょう。
ジェズイットを見習え |