複数の製品インスタンス (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
抽象工場から抽象製品を生成し、抽象製品を用いた (複雑な) 手順でアウトプットを出します。
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
}
}
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();
}
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