Abstract Factory パターン (互いに関連する一連のオブジェクト群を, その具象クラスに依存しないで生成するためのインタフェースを提供する)

[Abstract Factory] という単語は, [抽象的工場] を意味する.

このパターンは, 関連の一連のオブジェクト群をまとめて生成する方法を提供するパターン. このパターンを適用すると, 上記関連オブジェクトグループ単位での入れ替え, 追加が容易に行える.

よく似たパターンに [Factory Method] パターンがあるが, [Factory Method] パターンは, [オブジェクト生成] の抽象化にポイントを置いたパターンであるのに体し, [Abstract Factory] パターンは, [関連するオブジェクト群をまとめて生成するための手順] の抽象化にある.

役割

  1. AbstractProduct[1,2,3] (抽象的な製品):
[AbstractFactory] (抽象的な工場) によって生成される抽象的なオブジェクト (部品, 製品) のインタフェースを定義する.
  1. ConcreteProduct[A1,A2,A3], ConcreteProduct[B1,B2,B3] (具体的製品):
AbstractProduct[1,2,3] のインタフェースを実装する.
  1. AbstractFactory (抽象的な工場):
AbstractProduct[1,2,3] を生成するためのインタフェースを定義する. Factory オブジェクト ConcreteFactory[A,B] (具体的な工場) を生成するためのクラスメソッドを定義する.
  1. ConcreteFactory[A,B] (具体的な工場):
[AbstractFactory] のインタフェースを実装する.
  1. Client(利用者):
AbstractProduct[1,2,3], [AbstractFactory] が提供するインタフェースのみを使用して処理を行う.

クラス図

Abstract Factory パターンのクラス図

_images/designpattern-abstract_factory014.gif

ソースコード

  1. AbstractProduct1.java
1
2
3
4
5
6
7
8
9
public abstract class AbstractProduct1{
    protected String name; // 抽象クラスはインスタンス化できない
    
    public AbstractProduct1(String name){
	this.name = name;
    }

    public abstract void execute();
}
  1. AbstractProduct2.java
1
2
3
4
5
6
7
8
9
public abstract class AbstractProduct2{
    protected String name;

    public AbstractProduct2(String name){
	this.name = name;
    }
    
    public abstract void run();
}
  1. AbstractProduct3.java
1
2
3
4
5
6
7
8
9
public abstract class AbstractProduct3{
    protected String name;

    public AbstractProduct3(String name){
	this.name = name;
    }

    public abstract void action();
}
  1. ConcreteProductA1.java
1
2
3
4
5
6
7
8
9
public class ConcreteProductA1 extends AbstractProduct1{
    public ConcreteProductA1(String name){
	super(name);
    }

    public void execute(){
	System.out.println(name + " 完成(A1-execute)!");
    }
}
  1. ConcreteProductA2.java
1
2
3
4
5
6
7
8
9
public class ConcreteProductA2 extends AbstractProduct2{
    public ConcreteProductA2(String name){
	super(name);
    }

    public void run(){
	System.out.println(name + " 完成(A2-run)!");
    }
}
  1. ConcreteProductA3.java
1
2
3
4
5
6
7
8
9
public class ConcreteProductA3 extends AbstractProduct3{
    public ConcreteProductA3(String name){
	super(name);
    }

    public void action(){
	System.out.println(name + " 完成(A3-action)");
    }
}
  1. ConcreteProductB1.java
1
2
3
4
5
6
7
8
9
public class ConcreteProductB1 extends AbstractProduct1{
    public ConcreteProductB1(String name){
	super(name);
    }

    public void execute(){
	System.out.println(name + " 完成(B1-execute)!");
    }
}
  1. ConcreteProductB2.java
1
2
3
4
5
6
7
8
9
public class ConcreteProductB2 extends AbstractProduct2{
    public ConcreteProductB2(String name){
	super(name);
    }

    public void run(){
	System.out.println(name + " 完成(B2-run)!");
    }
}
  1. ConcreteProductB3.java
1
2
3
4
5
6
7
8
9
public class ConcreteProductB3 extends AbstractProduct3{
    public ConcreteProductB3(String name){
	super(name);
    }

    public void action(){
	System.out.println(name + " 完成(B3-action)");
    }
}
  1. AbstractFactory.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public abstract class AbstractFactory{
    public static AbstractFactory createFactory(int factoryId){
	switch(factoryId){
	case ConcreteFactoryA.id:
	    return new ConcreteFactoryA();
	case ConcreteFactoryB.id:
	    return new ConcreteFactoryB();
	default:
	    return null;
	}
    }

    public abstract AbstractProduct1 createProduct1();
    public abstract AbstractProduct2 createProduct2();
    public abstract AbstractProduct3 createProduct3();
}
  1. ConcreteFactoryA.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class ConcreteFactoryA extends AbstractFactory{
    public static final int id = 1;

    public AbstractProduct1 createProduct1(){
	return new ConcreteProductA1("工場A-製品1");
    }
    
    public AbstractProduct2 createProduct2(){
	return new ConcreteProductA2("工場A-製品2");
    }
    
    public AbstractProduct3 createProduct3(){
	return new ConcreteProductA3("工場A-製品3");
    }
}
  1. ConcreteFactoryB.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class ConcreteFactoryB extends AbstractFactory{
    public static final int id = 2;

    public AbstractProduct1 createProduct1(){
	return new ConcreteProductB1("工場B-製品1");
    }

    public AbstractProduct2 createProduct2(){
	return new ConcreteProductB2("工場B-製品2");
    }

    public AbstractProduct3 createProduct3(){
	return new ConcreteProductB3("工場B-製品3");
    }
}
  1. Client.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Client{
    public static void main(String[] args){
	List<AbstractFactory> factorys = new ArrayList<AbstractFactory>();
	
	factorys.add(AbstractFactory.createFactory(ConcreteFactoryA.id));
	factorys.add(AbstractFactory.createFactory(ConcreteFactoryB.id));

	Iterator<AbstractFactory> it = factorys.iterator();

	while(it.hasNext()){
	    AbstractFactory factory = it.next();
	    AbstractProduct1 product1 = factory.createProduct1();
	    AbstractProduct2 product2 = factory.createProduct2();
	    AbstractProduct3 product3 = factory.createProduct3();

	    product1.execute();
	    product2.run();
	    product3.action();
	}
    }
}

上記のプログラムの実行結果:

[wtopia AbstractFactory]$ java Client
工場A-製品1 完成(A1-execute)!
工場A-製品2 完成(A2-run)!
工場A-製品3 完成(A3-action)
工場B-製品1 完成(B1-execute)!
工場B-製品2 完成(B2-run)!
工場B-製品3 完成(B3-action)