第3章 Template Method - 増補改訂版Java言語で学ぶデザインパターン入門
第3章は、Template Method。こっちより委譲を使いたいときの方が多い…。というわけで、さくっといこっと。
Teplate Methodパターンの特徴は、次のとおり。
- 抽象クラスで処理の大枠を定める。
- そのサブクラスで、処理の内容を実装する。
処理の大枠は、スーパークラスで実装する必要がある。そのため、スーパークラスには、インタフェースでなく抽象クラスを使う。
クラントのコードからの使い方は、次のとおり。
このとき、リスコフの置換原則を守りましょう、とあります。クライント側のコードで処理を選ぶとき、if (instansof…) などと書かずに済むようにします。
また、処理の大枠を定義したメソッドをfinal宣言するとよいようです。サブクラスにオーバーライドされないようにするためです。
継承を使うことについて
Template Methodパターンを利用すると、処理の大枠の流れを規定することができます。一方、サブクラスは、抽象クラスで定義した処理をすべて実装する必要があります。いわゆる「サブクラスの責任」が生じます。
これが厄介で、Templateを拡張しづらい。結局、委譲の方が使い勝手がよいと感じてしまう。Template Methodパターンを使わなければいけない局面って、どんなときなんだろう?
そう思ってちょろっと調べたら、こんな文章に出会いました。
子クラスごとに異なる処理をするメソッドが、単独では意味を為さず、Template Methodから呼ばれるためだけに存在するような場合は、他のクラスからは隠蔽した方が良い。即ち、 Template Methodパターンの使用例として最適なケースは、子クラスごとの差異を表す抽象メソッドが、protectedメソッドであるような場合である。
Template Methodパターン
なるほど。とりあえず、次のような状況でのみ、Template Methodを使うことにします。
- Templateで定めた大枠の流れを固く守りたいとき
- Templateの特化バージョンを複数必要とするとき
Template Methodというか、継承を使うのに適した状況かどうかの見極めが、大事なのかも。
上で、final宣言のことを書いたけれど、GoF本では「Template Methodをオーバーライドさせるな」といっているらしい。たしかに、処理の大枠をオーバーライドして処理の内容を書き換える必要があるなら、それは、ようするにTemplate Methodに向いてないってことだと思う。
第3章は、ここまで。ほんとにさくっと終わってしまった。(ま、いっか)