Template Methodパターンとは、処理の流れを定めるテンプレートを持つクラスを作り、具体的な処理の詳細はサブクラスで定義するというデザインパターンだ。これにより、基本的な流れを共通化しつつ、個々の処理内容を柔軟に変更できる。
たとえば、朝のルーティンを考えてみよう。基本的な流れは決まっているけど、起きる時間や食べる朝ごはんは人によって違う。こうした「共通の流れ」と「個別の部分」を分けるのがTemplate Methodパターンだ。
では、サンプルコードを一緒に見ていこう。
まず、「朝のルーティン」のような、基本的な流れを定義するクラスを作る。このクラスには、朝の準備をするメソッド
morningRoutine()
があり、具体的な処理は後で決める部分がある。
// 朝のルーティンを定義するクラス
class MorningRoutine {
doRoutine() {
this.wakeUp(); // 起きる
this.haveBreakfast(); // 朝ごはんを食べる
this.getDressed(); // 服を着る
}
wakeUp() {
console.log("起きる時間は決まっている");
}
// 朝ごはんと服を着る部分は個別に定義する
haveBreakfast() {
throw new Error("このメソッドはサブクラスで実装してください");
}
getDressed() {
throw new Error("このメソッドはサブクラスで実装してください");
}
}
次に、それぞれの人の具体的な朝のルーティンを定義しよう。たとえば、「Aさん」はパンを食べるし、「Bさん」はご飯を食べるかもしれない。
// Aさんのルーティン
class PersonA extends MorningRoutine {
haveBreakfast() {
console.log("Aさんはパンを食べる");
}
getDressed() {
console.log("AさんはTシャツを着る");
}
}
// Bさんのルーティン
class PersonB extends MorningRoutine {
haveBreakfast() {
console.log("Bさんはご飯を食べる");
}
getDressed() {
console.log("Bさんはスーツを着る");
}
}
最後に、それぞれの人のルーティンを呼び出してみよう。基本的な流れは同じだが、個々の部分が異なる点に注目だ。
// AさんとBさんのルーティンを実行
const personA = new PersonA();
const personB = new PersonB();
console.log("Aさんのルーティン:");
personA.doRoutine(); // 結果: 起きる時間 -> Aさんはパン -> AさんはTシャツ
console.log("\nBさんのルーティン:");
personB.doRoutine(); // 結果: 起きる時間 -> Bさんはご飯 -> Bさんはスーツ
これでTemplate Methodパターンの解説は終わりだ。
このパターンを使うと、基本的な流れは固定しつつ、細かい部分を自由に変更できるので、共通の処理が多いときに便利だ。