概要
テンプレートメソッドとはOOPの代表的なデザインパターンの一つで、
CSVインポートとXMLインポートなど、大まかな流れは似てるけど細かいところが違う処理を複数作成する必要があるときに、
- 一つのクラス内で各ステップをメソッド化し、同じクラス内の別のメソッドでそれらを順番に実行するようにする
- 上記のクラスの子クラスでメソッドの内容を適宜上書きすることでいろいろな仕様に対応できるようにする
というものです。特に親クラスの「それらを順番に実行する」メソッドが「テンプレートメソッド」と呼ばれます。
親クラスが「我々を呼ばないでください、我々が呼びます」と言っているという意味で「ハリウッド原則」と呼ばれることもあるようです。
これはデザインパターンを知らなくても似たようなことをやったことがある人が多いのではないかなと思います。
埋め込み方法
親クラス
- 必要なステップをそれぞれメソッドに格納する。
- テンプレートメソッド内で上記の処理を実行する。
- 絶対上書きしてほしいメソッドは抽象メソッドにする。
- 上書きしなくてもいいメソッドはデフォルトの処理を書く。
- テンプレートメソッドは上書きされたくないので言語に上書きを防ぐ仕組みがあれば利用する。(javaやphpの
final
など) - 適宜フックを埋め込んでもいい(※後述)
public class Cat {
public final void introduce(){
String name = getName();
String meow = getMeow();
System.out.println("My name is %s. I meow like this: %s", name, meow);
}
public abstract String getName();
public abstract String getMeow();
}
public class Koro extends Cat {
public String getName() {
return "Koro";
}
public String getMeow() {
return "Meah";
}
}
public class Chobi extends Cat {
public String getName() {
return "Chobi";
}
public String getMeow() {
return "Mee";
}
}
フック
以下のように子メソッド内で親メソッドの前後の処理などをカスタマイズしたい場合は、
class Subclass extends Superclass
{
...
void something() {
// 前処理したい
super.something();
// 後処理したい
}
}
親メソッドの実装を読まなくてもよくするためあらかじめフック(空のメソッド)を用意するのもアリ。その場合はpre
やpost
のような前置詞を使ってわかりやすくする。
class Superclass
{
...
protected void preSomethingHook(){}
protected void postSomethingHook(){}
void something() {
preSomethingHook();
// なにかする
postSomethingHook();
}
}
class Subclass extends Superclass
{
protected void preSomethingHook()
{
// 前処理
}
protected void postSomethingHook()
{
// 後処理
}
}
参考
https://refactoring.guru/design-patterns/template-method
https://www.oodesign.com/template-method-pattern.html