テンプレートメソッドはビヘイビアデザインパターンに属し、ビヘイビアデザインパターンは主にオブジェクト間の責任とアルゴリズムの割り当てに焦点を当てています。クラス動作モデルは継承を使用してクラス間で責任を割り当て、テンプレートメソッドはクラス動作モデルです。オブジェクト動作モデルは、構成を使用して責任を割り当てます。ソフトウェア構築の過程で、ほとんどの場合、エンティティ間の責任について考えています。どのような責任が最も合理的で、重すぎず、軽すぎず、権限がないかを考えています。オブジェクト指向システムの分析および設計プロセスでは、このような状況に遭遇することがよくあります。特定のビジネスロジック(アルゴリズムの実装)では、さまざまなオブジェクトの実装が異なりますが、ロジック(アルゴリズム)フレームワーク(または一般的なアプリケーションアルゴリズム)同じです。テンプレートは、この状況の実装フレームワークを提供します。テンプレートモードでは、継承を使用してこれを実現します。ロジック(アルゴリズム)フレームワークを抽象基本クラスに配置し、詳細インターフェイスを定義して、サブクラスに詳細を実装します。【注1】
[注1]:ストラテジーモードはテンプレートモードと同様の問題を解決しますが、ストラテジーモードはロジックアルゴリズムをクラスにカプセル化し、組み合わせ(委任)メソッドを使用してこの問題を解決します。
1つは、テンプレートメソッドパターンとは何ですか
テンプレートメソッドパターンは、メソッド内のアルゴリズムのスケルトンを定義し、サブクラスへのいくつかのステップの実装を遅らせます。テンプレートメソッドを使用すると、サブクラスは、アルゴリズムの構造を変更せずに、アルゴリズムの特定のステップの特定の実装を再定義できます。
「デザインパターン」という4つの単語を見ると、予測できないことがよくありますが、テンプレートメソッドパターンは例外です。1つのメソッドだけに注意する必要があります。
テンプレートメソッドパターンは、継承メカニズムのみを使用する非常に単純ですが、非常に広く使用されているパターンです。
次に、テンプレートメソッドモードの使用シナリオ
システム内のアルゴリズムのフレームワークが固定されており、アルゴリズムの実装が多数ある可能性がある場合は、テンプレートメソッドモードを使用する必要があります。
- 複数のサブクラスには共通のメソッドがあり、ロジックは基本的に同じです
- 重要で複雑なアルゴリズムの場合、コアアルゴリズムはテンプレートメソッドとして設計でき、周囲の詳細な関数は各サブクラスによって実装されます。
- リファクタリングの場合、テンプレートメソッドは頻繁に使用されるメソッドであり、同じコードを親クラスに抽出し、コンストラクターを介してその動作を制約します。
例:レポート印刷プログラムを作成する必要があり、ユーザーはヘッダー、テキスト、およびフッターが必要であることを指定します。しかし、顧客のニーズは変化します。一方はこのようにヘッダーを表示し、もう一方はこのように表示したいと思うでしょう。
現時点では、テンプレートメソッドが適切です。
3つ目は、テンプレートメソッドパターンの長所と短所です。
利点:
- 定数部分をカプセル化し、可変部分を展開します。定数部分を考慮するアルゴリズムは親クラスにカプセル化され、変数部分は継承を通じて拡張できます。
- メンテナンスを容易にするために、コードの共通部分を抽出します。
- 動作は親クラスによって制御され、サブクラスによって実装されます
短所:
アルゴリズムスケルトンを変更する必要がある場合は、抽象クラスを変更する必要があります。
設計の習慣によれば、抽象クラスは物事の最も抽象的で一般的なプロパティとメソッドを宣言する責任があり、実装クラスは特定のトランザクションプロパティとメソッドを完了する責任がありますが、テンプレートメソッドは正反対です。サブクラス実行の結果は影響します親クラスの結果。コードの読み取りが難しくなります。
第四に、テンプレートメソッドパターンの実現
AbstractClassクラス---テンプレートメソッドを定義および実装する抽象テンプレートクラス。
このテンプレートは通常、最上位ロジックのスケルトンを提供する具体的なメソッドであり、論理構成ステップは、対応する抽象操作のサブクラス実装に委ねられます。
トップレベルロジックは特定のメソッドを呼び出すこともできます
#pragma once
//Template.h
class AbstractClass
{
public:
virtual ~AbstractClass();
void TemplateMethod();
protected:
virtual void PrimitiveOperation1() = 0;
virtual void PrimitiveOperation2() = 0;
AbstractClass();
private:
};
class ConcreteClass1:public AbstractClass
{
public:
ConcreteClass1();
~ConcreteClass1();
protected:
void PrimitiveOperation1();
void PrimitiveOperation2();
private:
};
class ConcreteClass2:public AbstractClass
{
public:
ConcreteClass2();
~ConcreteClass2();
protected:
void PrimitiveOperation1();
void PrimitiveOperation2();
private:
};
#include "stdafx.h"
#include "Template.h"
#include <iostream>
using namespace std;
AbstractClass::AbstractClass()
{
}
AbstractClass::~AbstractClass()
{
}
void AbstractClass::TemplateMethod()
{
this->PrimitiveOperation1();
this->PrimitiveOperation2();
}
ConcreteClass1::ConcreteClass1()
{
}
ConcreteClass1::~ConcreteClass1()
{
}
void ConcreteClass1::PrimitiveOperation1()
{
cout<<"ConcreteClass1...PrimitiveOperat ion1"<<endl;
}
void ConcreteClass1::PrimitiveOperation2()
{
cout<<"ConcreteClass1...PrimitiveOperat ion2"<<endl;
}
ConcreteClass2::ConcreteClass2()
{
}
ConcreteClass2::~ConcreteClass2()
{
}
void ConcreteClass2::PrimitiveOperation1()
{
cout<<"ConcreteClass2...PrimitiveOperat ion1"<<endl;
}
void ConcreteClass2::PrimitiveOperation2()
{
cout<<"ConcreteClass2...PrimitiveOperat ion2"<<endl;
}
int main(int argc, _TCHAR* argv[])
{
AbstractClass* p1 = new ConcreteClass1();
AbstractClass* p2 = new ConcreteClass2();
p1->TemplateMethod();
p2->TemplateMethod();
return 0;
}
テンプレートモードの実装コードは非常に単純なので、説明は冗長です。重要なのは、一般的なアルゴリズム(ロジック)をカプセル化し、サブクラスにアルゴリズムの詳細(ポリモーフィズム)を実装させることです。
注意すべき唯一のことは、テンプレートメソッド呼び出し(サブクラスが可能)に対してのみ、プリミティブ操作(詳細なアルゴリズム)を保護されていない(保護された)メンバーとして定義することです。
テンプレートモードは非常にシンプルなモードですが、広く使用されています。上記の分析と実装で説明したように、テンプレートは継承を使用して異種アルゴリズムを実現します。重要な点は、一般的なアルゴリズムを抽象基本クラスにカプセル化し、実装のためにサブクラスにさまざまなアルゴリズムの詳細を配置することです。
テンプレートモードは、逆制御構造効果を実現します。これは、オブジェクト指向システムの分析と設計における主要なDIP(依存性逆転の原則)でもあります。その意味は、親クラスが子クラスの操作(低レベルモジュールを呼び出す高レベルモジュールの操作)を呼び出し、低レベルモジュールが高レベルモジュールによって宣言されたインターフェイスを実装することです。このように、制御権は親クラス(高レベルモジュール)にあり、低レベルモジュールは代わりに高レベルモジュールに依存します。
継承の必須の制約関係もテンプレートモードを不十分にします。ConcreteClassクラスに実装されたプリミティブメソッドPrimitive1()は他のクラスで再利用できないことがわかります。AbstractClass AnotherAbstractClassのバリアントを作成する必要があり、2つは一般的なアルゴリズムが異なるだけで、プリミティブ操作はAbstractClassのサブクラスの実装を再利用したいとします。ただし、ConcreteClassはAbstractClassを継承し、AbstractClassはAbstractClassの一般的なアルゴリズムも継承するため、これは不可能です。AnotherAbstractClassは、ConcreteClassの実装を再利用できません。後者は、前者から継承されていないためです。
テンプレートモードで発生する問題は、継承に固有の問題でもあります。戦略モードでは、組み合わせ(委任)を使用して、テンプレートモードと同様の効果を実現します。コストは、スペースと時間のコストです。戦略モードの詳細については、 、戦略スキーマ分析を参照してください。