今回はTemplateMethodパターン。 『Java言語で学ぶデザインパターン入門』をベースにしているので、コードの意味などはこちらのJava版のソースコードを参照ください。
まずは素直にJavaのコードを移植したパターン(TemplateMethod1)。
Objective-Cには言語として抽象クラスのサポートがない。概念なのでプログラマーが勝手にやれよということらしい。で、サンプルコードではAbstractDisplay
という名前になっているが実際にはサブクラスで実装を期待するメソッドについては空メソッドを定義している。
-(void) open { }
-(void) print{ }
-(void) close{ }
呼び出す側のメイン関数も以下の通り
char c = 'H';
id d1 = [[CharDisplay alloc] initWithChar: c];
id d2 = [[StringDisplay alloc] initWithString:@"Hello World!"];
AbstractDisplay* d3 =
[[StringDisplay alloc] initWithString:@"日本語でこんにちは"];
[d1 display];
[d2 display];
[d3 display];
結果は以下のようになる。
<<HHHHH>>
+------------+
|Hello World!|
|Hello World!|
|Hello World!|
|Hello World!|
|Hello World!|
+------------+
+------------------+
|日本語でこんにちは|
|日本語でこんにちは|
|日本語でこんにちは|
|日本語でこんにちは|
|日本語でこんにちは|
+------------------+
これだけでは面白くないので、Objective-Cのクラスクラスタを使ってFactory的に実装してみる。(TemplateMethod2)
まず、AbstractDisplay
の+(id)allocを以下のように定義する。
+(id)alloc
{
self = [super alloc];
if([self isMemberOfClass:[AbstractDisplay class]]) {
PlaceHolderDisplay* disp = [PlaceHolderDisplay alloc];
return disp;
} else {
return self;
}
}
解説すると、最初に呼ばれたときには素直に親クラスのallocを呼び出し、自身がAbstractDisplay
だったときはPlaceHolderDisplay
をallocして返し、AbstractDisplay
でなかったときはそのまま自身を返す。
PlaceHolderDisplay
では、以下のように2つの初期化メソッドだけが定義されている。
-(id)initWithString:(NSString*) str
{
self = [[super init] autorelease];
StringDisplay* disp = [[StringDisplay alloc] initWithString:str];
return disp;
}
-(id)initWithChar:(char)ch
{
self = [[super init] autorelease];
CharDisplay* disp = [[CharDisplay alloc] initWithChar:ch];
return disp;
}
ここでやっていることも、初期化で呼び出された際それぞれ見合った子クラスのインスタンスを生成して返す。
Javaな人から見るとalloc
、つまりコンストラクタで自分とは別の子クラスのインスタンスを生成して返すなど邪道に思えるが、こうすることにより呼び出し側は以下のようになりこれらの子クラスのxxxxDisplayなどを意識することなくAbstractDisplay
クラスのみを使う感覚で使用できることになる。
id d1 = [[AbstractDisplay alloc] initWithChar:c];
id d2 = [[AbstractDisplay alloc] initWithString:@"Hello World!"];
AbstractDisplay* d3 = [[AbstractDisplay alloc] initWithString:@"日本語でこんにちは"];
実際、Cocoa/FoundationのNSString
クラスなどは抽象クラスで上記と同じような構成でデータ格納形式に応じて子クラスを生み分けているようだ。
コメント
コメントを投稿