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

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

使用法
テンプレート方式はフレームワークで使用され、ドメインのアーキテクチャの不変部分を実装しながら、カスタマイズ用のフックメソッドを提供します。これは制御の反転の例です。テンプレート方式が使用される理由は次の通りです。[3]
- サブクラスはフックメソッドをオーバーライドすることでさまざまな動作を実装できます。[6]
- コードの重複を回避します。アルゴリズムの一般的なワークフローは抽象クラスのテンプレートメソッドに一度実装され、必要なバリエーションはサブクラスに実装されます。[6]
- これは、特殊化が許可されるポイントを制御します。サブクラスがテンプレートメソッドを単純にオーバーライドすると、ワークフローに根本的かつ任意の変更を加えることができます。対照的に、フックメソッドのみをオーバーライドすると、ワークフローの特定の詳細のみを変更でき、[6]全体的なワークフローはそのまま残ります。
コードジェネレーターでの使用
テンプレート パターンは、自動生成されたコードを扱うときに便利です。生成されたコードを扱う際の課題は、ソース コードを変更すると、生成されたコードも変更されることです。生成されたコードに手書きの変更が加えられている場合、その変更は失われます。では、生成されたコードをどのようにカスタマイズすればよいのでしょうか。
テンプレートパターンは解決策を提供します。生成されたコードがテンプレートメソッドパターンに従う場合、生成されたコードはすべて抽象スーパークラスになります。手書きのカスタマイズがサブクラスに限定されている限り、コードジェネレーターはこれらの変更を上書きするリスクなしに再度実行できます。コード生成で使用される場合、このパターンは世代ギャップパターンと呼ばれることもあります。[7]
C++の例
この C++14 実装は、この本に記載されている C++98 以前の実装に基づいています。
#include <iostream> #include <メモリ>
class View { // AbstractClass public : // 具体的なサブクラスがアルゴリズムのステップを実装するために定義する抽象プリミティブ操作を定義します。 virtual void doDisplay () {} // アルゴリズムのスケルトンを定義するテンプレート メソッドを実装します。テンプレート メソッドは、プリミティブ操作だけでなく、AbstractClass または他のオブジェクトの操作で定義された操作も呼び出します。void display () { setFocus (); doDisplay (); resetFocus (); } virtual ~ View () = default ; private : void setFocus () { std :: cout << " View::setFocus \n " ; } void resetFocus () { std :: cout << "View::resetFocus \n " ; } };
class MyView : public View { // ConcreteClass // アルゴリズムのサブクラス固有のステップを実行するための基本的な操作を実装します。void doDisplay () override { // ビューのコンテンツをレンダリングしますstd :: cout << "MyView::doDisplay \n " ; } };
int main () { // スマートポインターはメモリリークを防ぎますstd :: unique_ptr < View > myview = std :: make_unique < MyView > (); myview -> display (); }
プログラムの出力は
ビュー:: setFocus
MyView :: doDisplay
ビュー:: 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 . バークレー、カリフォルニア州: Apress. p. 266. ISBN 978-1-4302-3331-2。
- ^ Vlissides, John (1998-06-22). パターンハッチング: デザインパターンの応用. Addison-Wesley Professional. pp. 85–101. ISBN 978-0201432930。
外部リンク
- テンプレートパターンの6つの一般的な用途
- テンプレートメソッド設計パターン
