- 必要性の指標
- 状況
- 方法
- 結果
- サンプルコード
- テストコード
- 注意事項
必要性の指標
頻度:★★★
重要度:★★★
状況
- アルゴリズムが変更される可能性がある
- アルゴリズムに共通する部分がある
- 構造はそのままに、アルゴリズムだけ入れ替えたい
方法
- 構造や変更のないメソッドの実装を、上位クラスで行なう
- 変更可能性のあるメソッドの実装を、下位クラスで行なう
構造や変更のないメソッドをテンプレートと呼ぶ。
変更可能性のあるメソッドをフックと呼ぶ。
すなわち、
こととなる。
変更可能性のあるメソッドをフックと呼ぶ。
すなわち、
テンプレートは、上位クラスで実装し、
フックは、下位クラスで実装する、
フックは、下位クラスで実装する、
こととなる。
- フックをあらかじめ、上位クラスで宣言しておく
- フックを呼び出すメソッドを、上位クラスで実装する
すなわち、
あらかじめ上位クラスで実装したものを、
下位クラスですり替える、
下位クラスですり替える、
こととなる。
結果
- 下位クラスで、メソッドに変更を加えられる。
- 上位クラスで実装したメソッドに対して、変更が適用される。
サンプルコード
- TAbstract :上位クラス
- TConcreate :下位クラス
- 上位クラスTAbstructの、hookOperationでは、空の文字列を返している
- 下位クラスTConcreateの、hookOperationでは、入力された文字列をそのまま返している
// NOTE =============================================
// Title : TemplateMethod
// =================================================
// License : MIT
// Author : Penguin-Works
// Make : 2013/08/04
// Finish : 2013/08/04
// LastSave : 2013/08/04
// =================================================
//
unit TemplateMethodUnit ;
interface
type
TAbstract = class// --------------------------------------------------------
published
function TemplateMethod( _str : string ):string ;
protected
function hookOperation( _str : string ) :string ; virtual ;
end ;
TConcreate = class( TAbstract )// ------------------------------------------
protected
function hookOperation( _str : string ) :string ; override ;
end ;
implementation
/// //////////////////////////////////////////////////////////////////////////
{ TAbstract }
function TAbstract.TemplateMethod( _str : string ): string ;
// ================================================
// Template Method
// ================================================
begin
// Call Hook Operation
Result := hookOperation( _str ) ;
end ;
function TAbstract.hookOperation( _str : string ): string ;
// ================================================
// Oparation Method
// ================================================
begin
Result := '' ;
end ;
/// //////////////////////////////////////////////////////////////////////////
{ TConcreate }
function TConcreate.hookOperation( _str : string ): string ;
// ================================================
//
// ================================================
begin
Result := _str ;
end ;
end.
テストコード
- TestTConcreate.TestTemplateMethod でテストをしている
- 文字列helloを、TConcreate.TemplateMethodに、入力している
- hookOperationの変更が反映されるならば、helloが返される。
- 反映されなければ、空の文字列が返される。
- テストコードでは、返り値が
- 空の文字列でないか?
- 入力した文字列と一致するか?
- 実行すると、上記テストがクリアできることを確認できる。
unit TestTemplateMethodUnit ;
{
Delphi DUnit テスト ケース
----------------------
}
interface
uses
TestFramework ,
TemplateMethodUnit ;
type
// クラスのテスト メソッド TConcreate
TestTConcreate = class( TTestCase )
strict private
FConcreate : TConcreate ;
public
procedure SetUp ; override ;
procedure TearDown ; override ;
published
procedure TestTemplateMethod ;
end ;
implementation
procedure TestTConcreate.SetUp ;
begin
FConcreate := TConcreate.Create ;
end ;
procedure TestTConcreate.TearDown ;
begin
FConcreate.Free ;
FConcreate := nil ;
end ;
procedure TestTConcreate.TestTemplateMethod ;
const
_nil : string = '' ;
var
_expect : string ;
_result : string ;
begin
_expect := 'hello' ;
_result := _nil ;
_result := FConcreate.TemplateMethod( _expect ) ;
CheckNotEqualsString( _nil , _result ) ;
CheckEqualsString( _expect , _result ) ;
end ;
initialization
// テスト ケースをテスト ランナーに登録する
RegisterTest( TestTConcreate.Suite ) ;
end.
注意事項
TConcreate.hookOperationにある、
overrideは、overloadと間違えやすい。
- overrideは再定義、(上書きなのでride)
- overloadは多重定義(同じ名前をいくつも呼びだすのでload)
となる。