[[デザインパターン]]

抽象生成構造(アブストラクトファクトリパターン)とでも言へる。抽象とは何ぞやと云つた時に、抽象化されるのはこのファクトリメソッドのインスタンスを使用する過程が抽象化されると云へる。
抽象生成構造(アブストラクトファクトリパターン)とでも言える。抽象とは何ぞやといった時に、抽象化されるのはこのファクトリメソッドのインスタンスを使用する過程が抽象化されると言える。

單純生成構造(ファクトリメソッド)では呼び出したメソッドが任意のクラスのインスタンスを生成して返す訣だが、抽象生成構造(アブストラクトファクトリメソッド)では更に「任意」のクラスのインスタンスを生成して返すことになる。
単純生成構造(ファクトリメソッド)では呼び出したメソッドが任意のクラスのインスタンスを生成して返す訳だが、抽象生成構造(アブストラクトファクトリメソッド)では更に「任意」のクラスのインスタンスを生成して返すことになる。


** Cocoa での例 [#kf36ec7c]
Objective-C の Cocoa API に定義される NSString(及び CFString、NSCFString)クラスをみる。表記體系が獨得なので PHP でコードすると、NSString や CFString は次のやうに呼び出すことになる。
 NSString::stringWithCString("任意のC文字列(char)","文字セットを示す定數");
 CFStringCreateWithCString(kCFAllocatorDefault,"任意のC文字列(char)","文字セットを示す定數");
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(實際には更にそのサブクラス)といふクラスが返され、これに對して指示をだすことになる。
CFStringCreateWithCString は Carbon API のクラスで、kCFAllocatorDefault は CFString クラスを生成したものが入っている。Carbon は C の API であるので、こういう風にインスタンスを渡すことでオブジェクト指向を表現する訳だ。ともかく、これらのコードは Mac OS X のアプリケーションでは共存可能であるということと、Cocoa API は Carbon API にラップされているらしいことを認識して欲しい。両者とも NSCFString(実際には更にそのサブクラス)というクラスが返され、これに対して指示を出すことになる。

stringWithCString といふメソッドでは、Carbon にラップ可能な時はラップするやうに實裝されるため、さう實裝される。他のクラス體系のファクトリメソッドを呼ぶ。かういつた集約構造を抽象生成構造など呼ぶ。具體的なインスタンス生成行程は別の所にあるのだと認識して欲しい。分つたやうな分らぬハナシ。
stringWithCString というメソッドでは、Carbon にラップ可能な時はラップするように実は裝されるため、そう実裝される。他のクラス体系のファクトリメソッドを呼ぶ。こういった集約構造を抽象生成構造など呼ぶ。具体的なインスタンス生成行程は別の所にあるのだと認識して欲しい。分ったような分らなかったような話でしたとさ。

** 結局抽象つて何なのさ [#l51845c4]
君だつて自分の作つた API 群があつたとして、その複雜な繼承關係であるとかを意識して單純生成(ファクトリメソッド)をするのは馬鹿げてると思はないか。今後、他のクラスインスタンスを生成したくなつた時に、全てのコードをそのクラスのファクトリメソッドを使用するやうに書き變へるのは現實的ではないと思はないか。
** 結局抽象って何なのさ [#l51845c4]
君だって自分の作った API 群があったとして、その複雜な継承関係であるとかを意識して単純生成(ファクトリメソッド)をするのは馬鹿げていると思わないか。今後、他のクラスインスタンスを生成したくなった時に、全てのコードをそのクラスのファクトリメソッドを使用するように書き続けるのは現実的ではないと思わないか。

これは豫めさういつた手段を考慮するものである。後者の例を PHP で擧げる。
これは予めそういった手段を考慮するものである。後者の例を PHP で挙げる。
 class decrepitFactory{
  static function factory(){
   return new self;
   }
  }
 
 class freshFactory{
  static function factory(){
   return new self;
   }
  }
 
 # 現在の實裝コードの状況
 # 現在の実裝コードの状況
 $obj = decrepitFactory::factory();
 $obj->method..... # 以下處理が續く
 $obj->method..... # 以下処理が続く


「decrepitFactory::factory」で呼び出す箇所は無數、至る所に及ぶ可能性は棄て切れぬ訣。もしこれを違ふクラスで實裝したい、「freshFactory::factory」、と思つても相當に手間である。
そこで最初から抽象化するとこれは解決できる。
「decrepitFactory::factory」で呼び出す箇所は無数、至る所に及ぶ可能性は捨て切れない。もしこれを違うクラスで実裝したい、「freshFactory::factory」、と思っていても相当に手間である。
そこで最初から抽象化する事で解決できる。

 class abstractFactory{
  static function factory(){
   # なんらかの判斷に基づき條件分岐
   # なんらかの判断に基づき条件分岐
   return decrepitFactory::factory();
   # 分岐
   return freshFactory::factory();
   }
 }

これで解決できた。OS、使用する言語バージョンでの分岐。分ける基準は色々ある。けれどもコードの上では「abstractFactory::factory」とするだけでクラスインスタンスが返される。ファクトリメソッドを變へることで苦惱することは無くなつた。
これで解決できた。OS、使用する言語バージョンでの分岐。分ける基準は色々ある。けれどもコードの上では「abstractFactory::factory」とするだけでクラスインスタンスが返される。ファクトリメソッドを變へることで苦悩することは無くなった。

更に云ふと、abstractFactory で大枠を實裝して、freshFactory や decrepitFactory は abstractFactory のサブクラスなどにする手段も考へられる。具體的なクラス名を意識することなく使用するのが主眼なので、同じメソッドを實裝すると宜しい。freshFactory だらうが decrepitFactory だらうが、然るべきメソッドは然るべき處理を施す。それが重要。
更に言うと、abstractFactory で大枠を実裝して、freshFactory や decrepitFactory は abstractFactory のサブクラスなどにする手段も考えられる。具体的なクラス名を意識することなく使用するのが主眼なので、同じメソッドを実装すると良い。freshFactory だらうが decrepitFactory だらうが、然るべきメソッドは然るべき処理を施す。それが重要。

この感覺はアダプタに近い所がある。データベースの種類を自動的に判別して接續するアダプタを切替るとかね。
この感覚はアダプタに近い所がある。データベースの種類を自動的に判別して接続するアダプタを切替えるとか。



20091226
中身は良いのに、変に旧字を使っていて読みにくかったので修正しました。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS