转自:http://www.techscore.com/tech/DesignPattern/TemplateMethod.html
第3章では TemplateMethod パターンを紹介します。 template とは、文字の形に穴があいている薄いプラスチックの板のことです。その穴をペンでなぞると、手書きでも整った文字を書くことができます。しかし、マジックで書くのか、鉛筆で書くのか、それとも墨汁と筆を使ってみるのかということを考えてみると、実際にどのような文字になるのかはわかりません。template は、ただその形を決定する枠組みを提供するだけです。
TemplareMethod パターンは、テンプレートの機能を持つパターンです。スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を実装します。スーパークラスでは、アルゴリズムの流れの中で利用される抽象的なメソッドと、この抽象的なメソッドを利用して、処理のアルゴリズムを定義する templateMethod メソッドを定義します。
今回は、生徒たちに木版画を教えます。簡単に大まかな流れを教えて、細かいことは生徒が自分で考えてやってもらうことにしました。木版画の作り方は、次のようになります。
これをプログラムに書いてみましょう。
public abstract class WoodCutPrint{ public abstract void draw( Cuttable hanzai ); public abstract void cut( Cuttable hanzai ); public abstract void print( Cuttable hanzai ); public void createWoodCutPrint(){ Wood hanzai = new Wood(); //Wood クラスは、Cuttable インタフェースを実装している draw( hanzai ); cut( hanzai ); print( hanzai ); } }
これでテンプレートは完成です。テンプレートとなる WoodCutPrint クラスでは、抽象メソッドである draw メソッド、 cut メソッド、print メソッド 定義しています。createWoodCutPrint メソッドでは、「版材」となる Cuttable インタフェースを実装 hanzai インスタンスを生成し、自らのクラスで定義している抽象メソッドを利用して、処理の流れを記述しています。どのように絵を描いて、どのように彫って、どのようにうプリントするのかは、すべてこれを継承するサブクラスの実装に任せられます。では、サブクラスはどのようになるでしょうか?田中君の木版画は以下のように作られるようです。
public class TanakasWoodCutPrint extends WoodCutPrint{ public void draw( Cuttable hanzai ){ hanzai にマジックを使って大好きな女の子の絵を描く; } public void cut( Cuttable hanzai ){ 彫刻刀を使って細部まで丁寧に hanzai を彫る; } public void print( Cuttable hanzai ){ 版画インクと馬簾を使って豪快にプリントする; } }
このように、TemplateMethod パターンでは、処理のアルゴリズムのみを定め、その処理の具体的な実装は、そのサブクラスに任せています。処理の大枠の手順に変更がない場合 TemplateMethod パターンの利用価値が高くなります。 サンプルケースのクラス図を見てみましょう。
TanakasWoodCutPrint クラスのインスタンスの createWoodCutPrint メソッドを呼び出せば、TanakasWoodCutPrint クラスで用意されている draw 、cut 、print の各メソッドが呼び出されます。
TemplateMethod パターンを利用することで、クラスの全員が間違いなく木版画を作成することができます。もし、処理の流れをテンプレートにせず、 SomeonesWoodCutPrint クラスの中に記述していたらどんなことになるでしょう?クラスの全員がきちんとした流れに沿って木版画を作成できていたでしょうか?今回のような簡単な流れしかなければ、たいした問題も生じないかもしれませんが、もっと複雑な処理を行う必要があった場合、処理の流れを間違ってしまう生徒が出ていたかもしれませんね。
TemplateMethod パターンの典型的なクラス図は以下のようになります。