オブジェクト指向プログラミングにおいて、テンプレートメソッドは、 Gammaら[1]が著書『デザインパターン』で特定した動作 設計パターンの一つです。テンプレートメソッドはスーパークラス(通常は抽象スーパークラス)のメソッドであり、操作の骨組みを複数の高水準ステップで定義します。これらのステップ自体は、テンプレートメソッドと同じクラス内の追加のヘルパーメソッドによって実装されます。
ヘルパーメソッドは、サブクラスで具体的な実装を提供する必要がある抽象メソッド、またはスーパークラスに空のメソッド本体を持つフックメソッドのいずれかです。サブクラスはフックメソッドをオーバーライドすることで操作をカスタマイズできます(ただし、必ずしもそうする必要はありません)。テンプレートメソッドの目的は、操作の全体的な構造を定義し、サブクラスで特定のステップを改良または再定義できるようにすることです。[2]
概要
このパターンには 2 つの主要な部分があります。
- 「テンプレートメソッド」は、基底クラス(通常は抽象クラス)のメソッドとして実装されます。このメソッドには、アルゴリズム全体の中で不変な部分のコードが含まれます。テンプレートは、包括的なアルゴリズムが常に実行されることを保証します。[1] テンプレートメソッドでは、アルゴリズムの中で変化する可能性のある部分は、追加のヘルパーメソッドの実行を要求するselfメッセージを送信することで実装されます。基底クラスでは、これらのヘルパーメソッドにはデフォルトの実装が与えられているか、あるいは全く実装されていない(つまり、抽象メソッドである)場合があります。
- 基本クラスのサブクラスは、「テンプレート」の空の部分、つまり「バリアント」の部分を、サブクラスごとに異なる特定のアルゴリズムで「埋める」。[3]サブクラスがテンプレートメソッド自体をオーバーライドしないことが重要だ。
実行時には、テンプレートメソッドによって表されるアルゴリズムは、具体的なサブクラスのインスタンスにテンプレートメッセージを送信することで実行されます。継承によって、基底クラスのテンプレートメソッドが実行を開始します。テンプレートメソッドが自身にヘルパーメソッドを要求するメッセージを送信すると、そのメッセージは具体的なサブインスタンスによって受信されます。ヘルパーメソッドがオーバーライドされている場合は、サブインスタンス内のオーバーライド実装が実行されます。オーバーライドされていない場合は、基底クラスで継承された実装が実行されます。このメカニズムにより、アルゴリズム全体が毎回同じ手順を実行することが保証されますが、一部の手順の詳細は、アルゴリズム実行の元の要求をどのインスタンスが受信したかによって異なります。
このパターンは、高レベルのコードではどのアルゴリズムを実行するかが決定されなくなり、代わりに実行時に低レベルのアルゴリズムが選択されるという、 制御の反転の例です。
テンプレートメソッドが送信する自己メッセージの一部は、フックメソッドへのものとなる場合があります。 これらのメソッドはテンプレートメソッドと同じ基底クラスに実装されていますが、メソッド本体は空です(つまり、何も実行しません)。フックメソッドは、サブクラスでオーバーライドできるようにするために存在します。これにより、テンプレートメソッド自体をオーバーライドすることなく、アルゴリズムの動作を微調整できます。言い換えれば、フックメソッドは、バリアント実装を「引っ掛ける」ための「フック」を提供します。
構造
UMLクラス図

上記のUML クラス図では、動作のスケルトン(テンプレート)を定義する操作
AbstractClassを定義しています。templateMethod()
- 動作の不変部分を実装し、
- および のメッセージを 自分自身に送信します。これらは で実装されているため、そのサブクラスはアルゴリズムのこれらの部分のさまざまな実装を提供できます。
primitive1()primitive2()SubClass1

使用法
テンプレート方式はフレームワークで用いられます。フレームワークでは、ドメインのアーキテクチャの不変部分を実装しつつ、カスタマイズ用のフックメソッドを提供します。これは制御の反転の一例です。テンプレート方式が用いられる理由は以下のとおりです。[3]
- サブクラスはフックメソッドをオーバーライドすることでさまざまな動作を実装できます。 [6]
- コードの重複を避ける:アルゴリズムの一般的なワークフローは抽象クラスのテンプレートメソッドに一度実装され、必要なバリエーションはサブクラスに実装されます。[6]
- これは、特化が許可されるポイントを制御します。サブクラスがテンプレートメソッドを単純にオーバーライドすると、ワークフローに根本的かつ恣意的な変更を加えることができます。対照的に、フックメソッドのみをオーバーライドすることで、ワークフローの特定の詳細のみを変更でき、[6]ワークフロー全体はそのまま残ります。
コードジェネレーターと併用する
このセクションの文体やスタイルは、Wikipedia で使用されている百科事典的な文体を反映していない可能性があります。より良い記事を書くための ( 2025年11月) |
テンプレートパターンは、自動生成されたコードを扱う際に便利です。自動生成されたコードを扱う際の課題は、ソースコードを変更すると、生成されたコードにも変更が反映されることです。生成されたコードに手書きで変更を加えた場合、その変更は失われてしまいます。では、自動生成されたコードはどのようにカスタマイズすればよいのでしょうか?
テンプレートパターンは解決策を提供します。生成されたコードがテンプレートメソッドパターンに従っている場合、生成されるコードはすべて抽象スーパークラスになります。手書きのカスタマイズがサブクラスに限定されている限り、コードジェネレーターはこれらの変更を上書きするリスクなしに再度実行できます。コード生成で使用される場合、このパターンは世代ギャップパターンと呼ばれることもあります。[7]
C++の例
この C++23 実装は、この本にある C++98 以前の実装に基づいています。
stdをインポートします。
std :: unique_ptrを使用します。
// 抽象クラス
class View { private : void setFocus () { std :: println ( "View::setFocus が呼び出されました" ); }
void resetFocus () { std :: println ( "View::resetFocus が呼び出されました" ); } public : // 具体的なサブクラスがアルゴリズムのステップを実装するために定義する抽象プリミティブ操作を定義します。virtual void doDisplay ( ) = 0 ;
// アルゴリズムの骨組みを定義するテンプレートメソッドを実装します。テンプレートメソッドは、プリミティブ操作に加えて、AbstractClassや他のオブジェクトの操作も呼び出します。void
display ( ) { setFocus (); doDisplay (); resetFocus (); }
仮想~ View () =デフォルト; };
// 具体的なクラス
class MyView : public View { public : // アルゴリズムのサブクラス固有のステップを実行するための基本的な操作を実装します。void doDisplay () override { // ビューの内容をレンダリングしますstd :: println ( "MyView::doDisplay が呼び出されました" ); } };
int main ( int argc , char * argv []) { unique_ptr < View > myview = std :: make_unique < MyView > (); myview -> display (); }
プログラムの出力は
View :: setFocusが呼び出され、MyView :: doDisplayが呼び出され、View :: resetFocusが呼び出されました
参照
参考文献
- ^ ab ガンマ, エリック;ヘルム, リチャード;ジョンソン, ラルフ;ブリシデス, ジョン(1994). 「テンプレートメソッド」.デザインパターン. アディソン・ウェズレー. pp. 325–330. ISBN 0-201-63361-2。
- ^ フリーマン, エリック; フリーマン, エリザベス; シエラ, キャシー; ベイツ, バート (2004). ヘンドリクソン, マイク; ルーキデス, マイク (編). Head First Design Patterns (ペーパーバック) . 第1巻. O'REILLY. pp. 289, 311. ISBN 978-0-596-00712-6. 2012年9月12日閲覧。
- ^ ab 「テンプレートメソッド設計パターン」。ソース作成 - ITプロフェッショナル向け教育。2012年9月12日閲覧。
テンプレートメソッドはフレームワークで広く使用されています。
- ^ 「テンプレートメソッド設計パターン - 構造」w3sDesign.com . 2017年8月12日閲覧。
- ^ LePUS3の凡例。http://lepus.org.uk/ref/legend/legend.xmlから取得。
- ^ abc Chung, Carlo (2011). Pro Objective-C Design Patterns for iOS . Berkeley, CA: Apress. p. 266. ISBN 978-1-4302-3331-2。
- ^ Vlissides, John (1998-06-22). 『パターンハッチング:デザインパターンの応用』Addison-Wesley Professional. pp. 85– 101. ISBN 978-0201432930。
外部リンク
- テンプレートパターンの6つの一般的な用途
- テンプレートメソッド設計パターン