CompositeパターンとCommandパターンの事例
着目するポイント
一般的なChain of ResponsibilityパターンはConcreteHandler役が「チェーン構造」と「要求に対する処理」の両方の責務を持つように設計します。しかし、「チェーン構造」は特殊なケースを除いては同じ操作と構造になるはずです。なぜなら「チェーン構造」の役割はConcreteHandler役をチェーンにつないだり、変更したり、削除したりできればよいからです。
一方、「要求に対する処理」は要求ごとに処理を用意する必要があります。よって、それらの処理は重複することがなく、すべて異なります。
汎用的なフレームワークを実現する以上、「チェーン構造」に関する機能はフレームワーク側で提供し、フレームワークの利用者は「要求に対する処理」に集中してプログラミングできるようにするべきです。
今回は「チェーン構造」と「要求に対する処理」を切り離すところに着目して、汎用的なフレームワークを作成します。
チェーン構造をツリー構造に置き換える
まずは図2-1をご覧ください。Chain of Responsibilityパターンのチェーン構造はConcreteHandler役のスーパークラスであるHandler役が持っています。Handler役は自分自身の関連を持つことでチェーン構造を実現しています。そのためサブクラスであるConcreteHandler役にもその特性が継承されます。
ConcreteHandler役からチェーン構造を取り除くため、Handler役のチェーン構造の部分にCompositeパターンを適用します。Compositeパターン適用後のクラス図を見るとComponent役とComposite役の関係で再帰的な構造を実現していることがわかります。その再帰的な構造は、図2-2のようなツリー構造に変化します。その図を見てわかるようにComposite役がツリー構造を管理する役割を持ち、Leaf役が要求に対する処理の役割を持つように分かれます。
Chain of Responsibilityパターンのチェーン構造を、Compositeパターンを適用したツリー構造に置き換えることで、ConcreteHandler役が抱えていた「チェーン構造」と「要求に対する処理」の両方の責務を持つ問題を解決できます。