抽象生成構造(アブストラクトファクトリパターン)とでも言へる。抽象とは何ぞやと云つた時に、抽象化されるのはこのファクトリメソッドのインスタンスを使用する過程が抽象化されると云へる。
單純生成構造(ファクトリメソッド)では呼び出したメソッドが任意のクラスのインスタンスを生成して返す訣だが、抽象生成構造(アブストラクトファクトリメソッド)では更に「任意」のクラスのインスタンスを生成して返すことになる。
Objective-C の Cocoa API に定義される NSString(及び CFString、NSCFString)クラスをみる。表記體系が獨得なので PHP でコードすると、NSString や CFString は次のやうに呼び出すことになる。
NSString::stringWithCString("任意のC文字列(char)","文字セットを示す定數"); CFStringCreateWithCString(kCFAllocatorDefault,"任意のC文字列(char)","文字セットを示す定數");
CFStringCreateWithCString は Carbon API のクラスで、kCFAllocatorDefault は CFString クラスを生成したものが入つてゐる。Carbon は C の API であるので、かういふ風にインスタンスを渡すことでオブジェクト指向を實現する訣。ともかくも、これらのコードは Mac OS X のアプリケーションでは共存可能であるといふことと、Cocoa API は Carbon API にラップされてるらしいことを認識して欲しい。兩者とも NSCFString(實際には更にそのサブクラス)といふクラスが返され、これに對して指示をだすことになる。
stringWithCString といふメソッドでは、Carbon にラップ可能な時はラップするやうに實裝されるため、さう實裝される。他のクラス體系のファクトリメソッドを呼ぶ。かういつた集約構造を抽象生成構造など呼ぶ。具體的なインスタンス生成行程は別の所にあるのだと認識して欲しい。分つたやうな分らぬハナシ。
君だつて自分の作つた API 群があつたとして、その複雜な繼承關係であるとかを意識して單純生成(ファクトリメソッド)をするのは馬鹿げてると思はないか。今後、他のクラスインスタンスを生成したくなつた時に、全てのコードをそのクラスのファクトリメソッドを使用するやうに書き變へるのは現實的ではないと思はないか。
これは豫めさういつた手段を考慮するものである。後者の例を PHP で擧げる。
class decrepitFactory{ static function factory(){ return new self; } } class freshFactory{ static function factory(){ return new self; } } # 現在の實裝コードの状況 $obj = decrepitFactory::factory(); $obj->method..... # 以下處理が續く
「decrepitFactory::factory」で呼び出す箇所は無數、至る所に及ぶ可能性は棄て切れぬ訣。もしこれを違ふクラスで實裝したい、「freshFactory::factory」、と思つても相當に手間である。 そこで最初から抽象化するとこれは解決できる。
class abstractFactory{ static function factory(){ # なんらかの判斷に基づき條件分岐 return decrepitFactory::factory(); # 分岐 return freshFactory::factory(); } }
これで解決できた。OS、使用する言語バージョンでの分岐。分ける基準は色々ある。けれどもコードの上では「abstractFactory::factory」とするだけでクラスインスタンスが返される。ファクトリメソッドを變へることで苦惱することは無くなつた。
更に云ふと、abstractFactory で大枠を實裝して、freshFactory や decrepitFactory は abstractFactory のサブクラスなどにする手段も考へられる。具體的なクラス名を意識することなく使用するのが主眼なので、同じメソッドを實裝すると宜しい。freshFactory だらうが decrepitFactory だらうが、然るべきメソッドは然るべき處理を施す。それが重要。
この感覺はアダプタに近い所がある。データベースの種類を自動的に判別して接續するアダプタを切替るとかね。