著作一覧 |
だからまじめに実装する気にはならず、常に直接ファクトリメソッドを実装し、中でいろいろやることにしている。
実際、どのくらいクソマジメに抽象ファクトリパターンを利用しているシステムってあるのだろうか?
たとえば、COMのIClassFactoryを考えてみる。確かにこれは抽象ファクトリなのだが、現実問題としてIClassFactoryを生成してから実際のオブジェクトを生成している人っているんだろうか? CoCreateInstanceを使ってるんじゃなかろうか(結局、同じことだし)。
Javaではどうだろうか。XMLReaderFactoryは抽象ファクトリではなく単なるスタティックメソッドとしてファクトリメソッドを提供している。内部ではプロパティからXMLReaderの実装クラス名を得て生成するから生成するオブジェクトについては十分に抽象化されていると言える。
抽象ファクトリパターンではなぜファクトリが抽象化されているかと言えば、ファクトリメソッドを抽象メソッドとしたいからに他ならない。しかし、代替手段があればそんな実装を行う必要はない。たとえば、IClassFactoryについて言えば、レジストリによってPROGID+CLSID+xServerエントリによってクラスがパラメタライズされているからCoCreateInstanceスタティックメソッド(というかWin32APIだから関数)で代替できる。Javaの場合、文字列からClass.forNameで実体化できるからXMLReaderFactoryはスタティックメソッドの提供で十分となる。
その一方でjavax.crypto.SecretKeyFactoryみたいに抽象ファクトリを教科書どおりに実装しているものもあるわけだが。
でも、SecretKeyFactory#getInstanceの引数をPROGIDと見立て、それをCLSIDと見立てたクラス名に変換して、そのクラス(KeySpecとProvider、SecretKey……というか、こいつは生成するオブジェクトの種類が多いからこれはこれで正解なのか)を返送するように実装したほうが素直ではないか? というか、java.sql.DriverManagerなんか、まさにそういうパターンのような(直接クラス名を指定してforNameで作れとなっている)。
むしろ、抽象ファクトリクラスよりも、オブジェクトそれ自身にファクトリメソッドを用意したほうが良い場合もあるのではないだろうか(実装固有の処理をクラス内に閉じるため)。
abstract class A {
public abstract A newInstance();
...
}
class B extends A {
private B(B org) { ... }
public A newInstance() { return new B(this); // Copy default settings }
}
class C extends A {
private C(C org) { ... }
public A newInstance() { return new C(this); // Copy default settings }
}
ジェズイットを見習え |