AbstractFactoryの実装例 (Java)
[履歴] [最終更新] (2013/08/24 22:09:35)
最近の投稿
注目の記事

概要

複数の製品インスタンス (ConcreteProduct1,2,3,...) を用いた複雑な手順で何らかのアウトプット1を出す場合を考えます。他にも同様の手順でアウトプット2,3,4,...を出すことを求められている場合、

抽象化した工場 (AbstractFactory) を用意しておき、抽象工場AbstractFactoryから抽象製品群 (AbstractProduct1,2,3,...) を生成できるようにし、「抽象製品群AbstractProduct1,2,3,...を用いてアウトプットnを出す複雑な手順」の共通化できる一部をテンプレートとして用意しておくと便利です。

各アウトプット1,2,3,...毎の差異となる具体的な部分は、抽象工場AbstractFactoryを継承した具体的な工場 (ConcreteFactory) および抽象製品AbstractProduct1,2,3,...を継承した具体的な製品群 (ConcreteProduct1,2,3,...) で実装します。

サンプルコード

フォルダ構成

$ tree .
.
|-- concrete1
|   |-- ConcreteFactory.java
|   |-- ConcreteProduct1.java
|   |-- ConcreteProduct2.java
|   `-- ConcreteProduct3.java
|-- factory
|   |-- AbstractFactory.java
|   |-- AbstractProduct1.java
|   |-- AbstractProduct2.java
|   |-- AbstractProduct3.java
|   `-- AbstractSuper.java
`-- sample.java

Main

抽象工場から抽象製品を生成し、抽象製品を用いた (複雑な) 手順でアウトプットを出します。

sample.java

import factory.AbstractFactory;
import factory.AbstractSuper;
import factory.AbstractProduct1;
import factory.AbstractProduct2;
import factory.AbstractProduct3; //具体的な工場および製品は利用しないためimportは不要

class Sample {
    public static void main(String args[]) {
        // 抽象的な工場を用意
        // - アウトプットnの形式 (concrete_i: n進数を扱う) はここで選択
        // - ここではconcrete1という、16進数を扱う工場を選択
        AbstractFactory factory = AbstractFactory.getFactory("concrete1.ConcreteFactory");

        // 抽象的な工場から複数の抽象的な製品を生成
        AbstractSuper product1 = factory.createProduct1('F'); //1桁目の数値を表現する製品
        AbstractSuper product2A = factory.createProduct2('5'); //2桁目の数値を表現する製品
        AbstractSuper product2B = factory.createProduct2('A'); //2桁目の数値を表現する製品
        AbstractProduct3 product3 = factory.createProduct3(); //合計を計算する製品

        // 複数の抽象的な製品を用いた (複雑な) 手順でアウトプットを出す
        product3.add(product1);
        product3.add(product2A);
        product3.add(product2B);
        System.out.println(product3.task()); //F+50+A0=FF=255
    }
}

Factory (抽象工場と抽象製品)

AbstractFactory.java

package factory;

public abstract class AbstractFactory {
    public static AbstractFactory getFactory(String classname) {
        AbstractFactory factory = null;
        try {factory = (AbstractFactory)Class.forName(classname).newInstance();}
        catch (Exception e) {e.printStackTrace();}
        return factory;
    }
    public abstract AbstractProduct1 createProduct1(char digit);
    public abstract AbstractProduct2 createProduct2(char digit);
    public abstract AbstractProduct3 createProduct3();
}

AbstractSuper.java

package factory;
public abstract class AbstractSuper {
    protected char digit;
    public AbstractSuper(char digit) {this.digit=digit;}
    public abstract int task();
}

AbstractProduct1.java

package factory; // 抽象クラスを継承する抽象クラス
public abstract class AbstractProduct1 extends AbstractSuper {
    public AbstractProduct1(char digit) {super(digit);}
}

AbstractProduct2.java

package factory; // 抽象クラスを継承する抽象クラス
public abstract class AbstractProduct2 extends AbstractSuper {
    public AbstractProduct2(char digit) {super(digit);}
}

AbstractProduct3.java

package factory;
import java.util.List;
import java.util.ArrayList;

public abstract class AbstractProduct3 {
    protected List<AbstractSuper> list=new ArrayList<AbstractSuper>();
    public void add(AbstractSuper abstractProduct) {list.add(abstractProduct);}
    public abstract int task();
}

Concrete1 (具体的な工場および製品)

ConcreteFactory.java

package concrete1;
import factory.*;
public class ConcreteFactory extends AbstractFactory {
    public AbstractProduct1 createProduct1(char digit) {return new ConcreteProduct1(digit);}
    public AbstractProduct2 createProduct2(char digit) {return new ConcreteProduct2(digit);}
    public AbstractProduct3 createProduct3() {return new ConcreteProduct3();}
}

ConcreteProduct1.java

package concrete1;
import factory.*;

public class ConcreteProduct1 extends AbstractProduct1 {
    public ConcreteProduct1(char digit) {super(digit);}
    public int task() {
        if('0' <= digit && digit <= '9') return digit-'0';
        else if ('A' <= digit && digit <= 'F') return digit-'A'+10;
        else return -1;
    }
}

ConcreteProduct2.java

package concrete1;
import factory.*;

public class ConcreteProduct2 extends AbstractProduct2 {
    public ConcreteProduct2(char digit) {super(digit);}
    public int task() {
        if('0' <= digit && digit <= '9') return (digit-'0')*16;
        else if ('A' <= digit && digit <= 'F') return (digit-'A'+10)*16;
        else return -1;
    }
}

ConcreteProduct3.java

package concrete1;
import factory.*;
import java.util.Iterator;

public class ConcreteProduct3 extends AbstractProduct3 {
    public int task() {
        int sum=0;
        Iterator it = list.iterator();
        while(it.hasNext()) sum += ((AbstractSuper)it.next()).task();
        return sum;
    }
}

実行例

$ javac sample.java factory/*.java concrete1/*.java && java Sample
255
関連ページ