Factoryパターン

factory.png

Factoryっていうけど、何を作るの?
オブジェクトを作るのです。
Fatoryクラスは、ある特定のオブジェクトを作るためだけのクラスなのです。
映画製作でいうと、役者さんを綺麗にするメイクアップ担当のような役割でもあります。
オブジェクトの生成が複雑なオブジェクトがあったら、Factoryクラスを作るとよいでしょう。

効果

  • 生成するオブジェクトの変更や修正が簡単にできる。
  • クラス同士の関連を抑える疎結合効果

使用例

  • 型変換するメソッドを作る

色々なFactoryまとめ

Abstract-Factory Factory-Method
public interface abstFactory{
abstract Product create();
}
public class Child extends abstClass{
@Override
Product factory(){
/***/
}
}
Abstract-Factory Factory-Method
クライアントの使用する実際の具体的な製品から分離されている
オブジェクトコンポジションを使ってオブジェクトを作成する 継承を使ってオブジェクトを作成する
一連の製品を作成するための抽象型を提供する。その抽象型のサブクラスは、それらの製品の作成方法を定義する。このファクトリを使用するには、ファクトリをインスタンス化し、それを抽象型に対して書かれたコードに渡す。
新しい製品を追加したら、インタフェースを変更しなきゃいけない その必要はない
具象ファクトリを実装する サブクラスが作成する具体的な型をりようする コードを抽象作成者で実装する
作成する必要のある一連の製品があり、クライアントがグループをなす製品を使用するようにしたい場合に使う インスタンス化する必要のある具象クラスからクライアントコードを分離するためや、必要となるすべての具象クラスが事前にわからない場合に使用する

Factoryの利点

利点をおおまかにまとめると、大体がコンストラクタにはできないけど、Factoryならできることなのである。

ある特定のオブジェクトの生成を1つのクラスに任せることによって、実装が変わった際に変更すべき部分が1つだけになって、保守が容易になる。

ちょっと実装が変わったとき、いっぱいいる子クラスのすべてのコンストラクタを変更するのは大変だってことなのかね?
何か変更があったら、一人一人の家を訪問して説明するんだったら、
一つのお教室に集めてまとめて説明する方が楽ってことね?

コンストラクタと違って、関数名なので、好きな名前がつけられる=名前がわかりやすくなる[2]

つまり、引数の違うコンストラクタを複数作るぐらいだったら、factoryメソッドにしたほうがマシってことだ。

コンストラクタと異なり、関数の戻り値型の任意の子クラスのオブジェクトで返すことができる。

これは、どのクラスのオブジェクトを返すかという選択の柔軟性を大きく広げる。

たとえばこんなかんじ

public Kardashian makeKardashian(int order){
    switch(order){
    case 0:
     return new Kourtney();//カーダシアン家の長女のコートニー
    case 1:
     return new Kim();//カーダシアン家の次女のキム
 
    default:
     return new Khloe();//カーダシアン家の三女のクロエ
    }
    }

戻り値はKardashianとしてあるけど、実際にはカーダシアン家の娘たちであればコートニーを返そうが、キムを返そうが構わないのである。

Map<int,String>などの型引数が面倒でなくなる

before after
Map<String,List<String>> m=new HashMap<String,List<String>();

これは長ったらしい。
Map<String,List<String>> m=HashMap.newInstane();

ちょこっとコードする量が減りますね。

newInstance()という名前のfactoryメソッドを定義する

public static <K,V> HashMap<K,V> newInstance(){
    return new HashMap<K,V>();
}

たとえば3DCGにおいてよく困るのが、レンダリングしたいオブジェクトが、テクスチャつきか、そうじゃないか、だけど、、、

Model makeModel(String type){
    Model model;
   if(type.equals("XYZ")){
        model=new Simple();
    }else if(type.equals("XYZUV")){
        model=new Textured();
    }else if(type.equals("XYZnXnYnZ")){
        model=new Shaded();
    }else{
       model=new TexturedShaded();
    }
    model.setupGeometry();
    model.loadTexture();
    model.createShader();
    model.createVBO();
return model;
}

もしこれにFactoryをつくるならば、こうなる
public class ModelFactory(){
    public Model createModel(){
        Model model=null;
   if(type.equals("XYZ")){
        model=new Simple();
    }else if(type.equals("XYZUV")){
        model=new Textured();
    }else if(type.equals("XYZnXnYnZ")){
        model=new Shaded();
   }else{
       model=new TexturedShaded();
    }
return model;
    }
}

Factoryが使用されている例

さて、Factoryが良いっていうけど、本当にみんな使ってんのかしら??と疑う人へ。。!
Factoryが実際に使用されているライブラリを紹介します。

  • libKml…..Google Earthでお馴染のkmlを扱うライブラリ.kmlFactoryというクラスがある。
  • BitmapFactory…AndroidのBitmapFactory.ファイルパス、InputStreamなどあらゆる引数でBitmapを自動生成してくれる。

短所

privateなコンストラクタしか持たないクラスのサブクラスは作れない[2]

クラスの修飾子自体がprivateであっても同じことが言える。
でも、コンストラクタをprivateにしたいときってどんなとき?シングルトンで使うんだっけ???
そういう風になったら、継承ではなくコンポジションを使えばよいのである

疑問

で、実際にFactoryを実装するときは、Factoryクラスを作るのか?
それとも何かのクラスにこそっと置いておくのか???
→Factoryのクラスを作ります"
biblabel: ''
bibliography: ''
bibname: ''


loose-coupling memory-consumption readability

サポートサイト Wikidot.com loose-couplingmemory-consumptionreadability