#22 / 23
B振る舞いDIFF
テンプレートメソッド
Template Method
レシピは同じ手順、具材だけが違う。親が骨格を握り、子が肉付けを担当する。
Intent · 目的
アルゴリズムの『流れ』は親クラスの中で固定し、変動する『各ステップの中身』はサブクラスでオーバーライドさせる。手順は一箇所に書かれ、肉付けは派生クラスごとに変えられる。
Motivation · 動機
「データを取ってきて → 整形して → 出力する」── この流れは JSON レポートでも CSV レポートでも同じ。違うのは『どこから取るか』『どう整形するか』だけ。それぞれを丸ごとコピペで2つ書くと、流れの修正のたびに両方を直すことになる。Template Method なら親に流れを書き、変動する2ステップだけサブクラスに任せる。料理本のレシピに例えるなら、「肉を切る」→「炒める」→「煮込む」の流れは共通、肉と調味料だけ違う、というようなもの。
適用場面
- 1アルゴリズムの全体手順は同じだが、特定のステップだけ実装が違う場面(レポート、テスト基盤、ゲームAIの行動ループ)。
- 2コードの重複を排除したいフレームワーク的な使い方。
- 3サブクラスでの拡張ポイントを明示したい場合。
概念図
サンプルコード
abstract class ReportGenerator {
generate(): string {
const raw = this.fetch();
const body = this.format(raw);
return this.decorate(body);
}
protected abstract fetch(): string;
protected abstract format(raw: string): string;
protected decorate(body: string){ return "=== Report ===\n" + body; }
}
class JsonReport extends ReportGenerator {
protected fetch(){ return JSON.stringify({ x: 1 }); }
protected format(raw: string){ return "JSON: " + raw; }
}
console.log(new JsonReport().generate());Pros · メリット
- +アルゴリズム共通の流れが1か所に集約され、コピペが消える。
- +ステップごとの拡張ポイントが明確で、サブクラス作成のガイドが効く。
- +親の流れを修正すれば、全サブクラスの挙動が一気に揃う。
Cons · デメリット
- −親クラスを変更すると全サブクラスに影響する。継承の鎖はそういうもの。
- −Strategy のように実行時に差し替えられない(型レベルで決まる)。
- −サブクラス側で意図せず親メソッドを上書きすると、リスコフ置換違反を起こしやすい。
関連パターン
⚔ ready to test
理解度を確かめる時間だ
3 問のクイズで、 このパターンを身体に染み込ませよう。