今回はGoF(Gang of Four)のデザインパターンの一つであるAbstract Factoryを実装・解説していきます。
AbstractFactoryとは?

画像: wikipediaより
AbstractFactoryは、共通の似たメソッドをもつそれぞれのFactoryをまとめる方法の一つです。
AbstractFactoryを使うクライアントクラスは、オブジェクトを生成する際にFactoryのジェネリックインターフェースを使います。
クライアントはジェネリックインターフェースしか使わないので、オブジェクトがどのFactoryから生成されたものなのかを気にする必要がありません。
これによって後から新しくProductA3とProductB3を追加したときにでも、クライアントはConcreteFactory3から今までと同じようにCreateProductA()とCreateProductB()を使えばいいので、プログラム全体の保守性が格段に良くなるわけです。
余談ですが、ProductA1とProductA3ではデータの型が違うはずなのにどうして同じCreateProductA()で返すことができるのかというのは、オブジェクト指向の多態性という性質がそのプログラミング言語でサポートされているからです。
実際にAbstractFactoryを使ったプログラム
今回の紹介するプログラムは以下のクラス図のような構成になっています。

このクラス図と冒頭で紹介したAbstractFactoryのクラス図を対応付けすると、
CarFactory — AbstractFactory
SuperCarFactory, TruckFactory, BusFactory — ConcreteFactory
Tire, Body — AbstractProduct
BigTire, SuperCarTire, SuperCarBody, TruckBody, BusBody — ConcreteProduct
Client — Client
となります。
早速コードを見ていきましょう。
1:CarFactory.java
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public abstract class CarFactory { /** */ public abstract Tire getTire(); /** */ public abstract Body getBody(); } |
2:SuperCarFactory.java, TruckFactory.java, BusFactory.java
1 2 3 4 5 6 7 8 9 10 11 |
public class SuperCarFactory extends CarFactory { public Tire getTire() { return new SuperCarTire(); } public Body getBody() { return new SuperCarBody(); } } |
1 2 3 4 5 6 7 8 9 10 11 |
public class TruckFactory extends CarFactory { public Tire getTire() { return new BigTire(); } public Body getBody() { return new TruckBody(); } } |
1 2 3 4 5 6 7 8 9 10 11 |
public class BusFactory extends CarFactory { public Tire getTire() { return new BigTire(); } public Body getBody() { return new BusBody(); } } |
3:Tire.java, Body.java
1 2 3 4 |
public abstract class Tire { } |
1 2 3 4 |
public class Body { } |
4:BigTire.java, SuperCarTire.java, SuperCarBody.java, TruckBody.java, BusBody.java
1 2 3 4 |
public class BigTire extends Tire { } |
1 2 3 4 |
public class SuperCarTire extends Tire { } |
1 2 3 4 |
public class SuperCarBody extends Body { } |
1 2 3 4 |
public class TruckBody extends Body { } |
1 2 3 4 |
public class BusBody extends Body { } |
5. 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 26 27 |
public class Client { /** */ public static void main(String[] args){ CarFactory cf = new SuperCarFactory(); Tire t = cf.getTire(); Body b = cf.getBody(); System.out.println(t.getClass().getSimpleName()); System.out.println(b.getClass().getSimpleName()); cf = new TruckFactory(); t = cf.getTire(); b = cf.getBody(); System.out.println(t.getClass().getSimpleName()); System.out.println(b.getClass().getSimpleName()); cf = new BusFactory(); t = cf.getTire(); b = cf.getBody(); System.out.println(t.getClass().getSimpleName()); System.out.println(b.getClass().getSimpleName()); } } |
3と4のproductに関しては、Factoryから生成するだけなのでメソッドやメンバは何一つありません。
2のそれぞれのgetTire()とgetBody()は各クラスで別の型のオブジェクトを生成し返していますが、
これらはTireとBodyのabstractクラスを継承しているクラスなので、多態性の性質を利用して返り値の型はBigTire型やBusBody型ではなくTire型, Body型となっています。
Client.javaでは、
1 2 3 |
System.out.println(t.getClass().getSimpleName()) |
の部分で、変数に格納されているオブジェクトのクラス名を出力しています。
このプログラムをコンパイルして実行すると、

と表示されていることが分かります。