第3章 Template Method - 増補改訂版Java言語で学ぶデザインパターン入門

第3章は、Template Method。こっちより委譲を使いたいときの方が多い…。というわけで、さくっといこっと。

Teplate Methodパターンの特徴は、次のとおり。

  • 抽象クラスで処理の大枠を定める。
  • そのサブクラスで、処理の内容を実装する。

処理の大枠は、スーパークラスで実装する必要がある。そのため、スーパークラスには、インタフェースでなく抽象クラスを使う。

クラントのコードからの使い方は、次のとおり。

  • 1. 抽象クラスの変数を宣言して、実装クラスのインスタンスを生成します。
  • 2. 実装クラスのインスタンス経由で、抽象クラスで定義した処理を呼び出します。

このとき、リスコフの置換原則を守りましょう、とあります。クライント側のコードで処理を選ぶとき、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章は、ここまで。ほんとにさくっと終わってしまった。(ま、いっか)