勉強日記

チラ裏

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をつける
    • 【補】「まさにその仕事をする実装部分」という気持ちがこめられている。たぶん。

関連するパターン

  • FactoryMethod
    • FactoryMethodはTemplate Methodから呼び出されること多し
  • Strategyとの対比
    • 共通点: ふるまいを切り分けてカスタム可能にする
    • 相違点
      • Strategy: オブジェクトの集約ベース
      • Template Method: クラスの継承ベース
    • 【補】Strategyのジェネリクス版で、EBO(Empty Base Optimization)を効かせるために継承ベースにした場合、それはもはやStrategyではなくTemplate Methodパターンである