Template Method
Template Methodパターンは、スーパークラスで処理の枠組みを定義して、 サブクラスでその具体的な処理を記述するパターンです。
例:フェラーリとBMWに乗って目的地に行く。
ソースはこちら
この例で言う「処理」とは、「車に乗って目的地に行く」というものです。 ここで考えなくてはならないのは、その処理の具体的な手順ですが、これはフェラーリでも BMWでも似たようなものですよね。2つとも「車」ですし、車を運転するときは、 「エンジンをかけて」、「目的地に向かい」、「エンジンを切る」という作業を決まって行います。 だけど、フェラーリとBMWではエンジンのかけ方が違うかもしれませんし、運転の仕方も、 エンジンの切り方も違うかも知れません。それでも大きく見れば似たような処理ですよね。 このような場合にはTemplate Methodパターンが有効です。

Template Methodでは処理の枠組み(フレームワーク)をスーパークラス側で定義し、 具体的な処理内容をサブクラス側で定義します。上の例だと「車に乗って目的地に行く」、 という処理はスーパークラスで記述します。そして、「エンジンをかける」、「目的地に向かう」、 「エンジンを切る」という処理をサブクラスで記述します。

ここで必要なクラスを洗い出して見ましょう。

DrivingCar 「車に乗って目的地に行く」という処理を表す抽象クラス
DrivingFerrari 「フェラーリに乗って目的地に行く」という処理を表すクラス
DrivingBmw 「BMWに乗って目的地に行く」という処理を表すクラス

具体的な実装方法としては、スーパークラス側の処理の枠組みを定義したメソッドは、 内部的な別のメソッドを呼び出すことで実装されます。そしてその内部的なメソッドを 抽象メソッドとし、サブクラス側で実装させます。こうすることで、スーパークラス側は サブクラスでの具体的な処理を知らなくても、「車に乗って目的地に行く」ことが出来ます。

また、このプログラムのメインクラスを見てもらえれば分かるように、DrivingFerrariと DrivingBmwのインスタンスはそれぞれ、DrivingCar型の変数、ferrariとbmwに代入されています。 ferrariとbmwには、厳密には違うインスタンスが入っているのに、driveメソッドの呼び出しにも 適切に応答しています。

これは一見すると奇妙ですが、当然のことです。何故ならDrivingFerrariと DrivingBmwは同じDrivingCarクラスを継承していて、driveメソッドはDrivingCarで定義されているからです。

今回のプログラムはごく小規模なものですから簡単ですが、これがもっと大きなものになると、 同じスーパークラスを継承したサブクラスでも、instanceofなどを使ってどのクラスなのか 参照しなければならないことが多くなるかも知れません。けれども、そのような処理をしなければならないと いうことは、概ね設計上に問題があります。「スーパークラス型の変数にはそのサブクラスであればどんな インスタンスを入れても正しく動作する」、という原則のことをLSPと言いますが、 これはデザインパターンに留まらず、継承の大原則です。 適切な実装を行えば、instanceofを使う必要がない場合がほとんどです。 実際、instanceofを用いるコードは、多態性(ポリモーフィズム)を利用することで同様の処理が実現可能です。 多態性というのは、まさにこのTemplate Methodを適用したようなコードに見られます。
実行結果
クラス図