GoF本 Template Method
ねらい
- アルゴリズムの骨組みを基底クラスで定義
- 実装を派生クラスにゆだねる
つかいどころ
- クラスを派生してカスタマイズしたい
- カスタマイズしても変わらない骨組みを共通化したい
- フックを提供したい
登場人物
- 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パターンである