ねらい
- アルゴリズムの骨組みを基底クラスで定義
- 実装を派生クラスにゆだねる
つかいどころ
- クラスを派生してカスタマイズしたい
- カスタマイズしても変わらない骨組みを共通化したい
- フックを提供したい
登場人物
-
AbstractClass
- 不変なアルゴリズムの骨組みを定義・実装 (Template Method)
- すべての派生クラスから利用されうる処理を実装
-
派生クラスに実装を委ねたい処理を抽象メソッドとして定義
- デフォルトの空動作を持たせるケース
- 空動作も持たせず、overrideを強制するケース
-
ConcreteClass
- AbstractClassの派生
- 抽象メソッドのoverride
結果
- コード共通化
-
フックの提供
-
何かの処理の直前・直後に呼ばれる仮想メソッドを定義しておく
- デフォルト何もしない
- 派生でoverrideする
-
- きめ細やかなoverride
これは良くない
// virtual
void AbstractClass::Operate() {
共通の処理();
}
// override
void ConcreteClass:Operate() {
AbstractClass::Operate(); // 呼び忘れやすい
追加の処理();
}
これがよい
// non-virtual
void AbstractClass::Operate() {
共通の処理();
DoOperate(); // virtual
}
// override
void ConcreteClass:DoOperate() {
追加の処理();
}
実装にあたり考えるべきこと
-
C++のアクセス制御
- overrideしたいメソッドをprotectedにする
- overrideされては困るTemplate Methodにはvirtualをつけない
-
overrideするメソッドをむやみに増やさない
- つかいづらい
-
命名規則
- overrideするメソッドには、例えば接頭辞
Do
をつける - 【補】「まさにその仕事をする実装部分」という気持ちがこめられている。たぶん。
- overrideするメソッドには、例えば接頭辞
関連するパターン
-
FactoryMethod
- FactoryMethodはTemplate Methodから呼び出されること多し
-
Strategyとの対比
- 共通点: ふるまいを切り分けてカスタム可能にする
-
相違点
- Strategy: オブジェクトの集約ベース
- Template Method: クラスの継承ベース
- 【補】Strategyのジェネリクス版で、EBO(Empty Base Optimization)を効かせるために継承ベースにした場合、それはもはやStrategyではなくTemplate Methodパターンである