Index
Java言語で学ぶデザインパターン入門第3版
参考書籍では以下のように書かれています。
Abstract Factoryパターンでは抽象的な工場が登場し、抽象的な部品を組み合わせて抽象的な製品を作ります。
部品の具体的な実装には注目せず、インターフェースに注目する。そして、そのインターフェースだけを使って部品を組みたて、製品にまとめるのです。
なにやら難しいことを言ってますね。
Abstract Factoryパターンはサンプルコードを見て理解するのが一番いいと思います。
似たようなパターンでFactory methodパターンがありますので、合わせてご覧ください。
FactoryMethodパターン@Java言語で学ぶデザインパターン入門
- 具体的な工場を新たに追加するのが簡単
詳細はサンプルコードを確認した後に見てみましょう。
Food,Drinkクラスのスーパークラスです。
このクラスはFood,Drinkクラスを同一視するためのクラスです。
1 2 3 4 5 6 7 8 9 10 11 |
package abstractfactory; public abstract class Item { protected final String m_name; public Item(final String name) { m_name = name; } public abstract String makeItem(); } |
食品名を保持するためのクラス
1 2 3 4 5 6 7 |
package abstractfactory; public abstract class AbstractFood extends Item { public AbstractFood(final String name) { super(name); } } |
飲料名を保持するためのクラス
1 2 3 4 5 6 7 |
package abstractfactory; public abstract class AbstractDrink extends Item{ public AbstractDrink(final String name) { super(name); } } |
工場を取得するためのクラスです。
getFactory()メソッドが厄介なのですが、引数(classname)で指定したFactoryクラスを取得しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package abstractfactory; public abstract class AbstractFactory { public static AbstractFactory getFactory(final String classname) { AbstractFactory factory = null; try { factory = (AbstractFactory)Class.forName(classname).getDeclaredConstructor().newInstance(); }catch(ClassNotFoundException e) { String.format("%sが見つかりませんでした", classname); }catch(Exception e) { e.printStackTrace(); } return factory; } public abstract AbstractFood createFood(final String name); public abstract AbstractDrink createDrink(final String name); } |
抽象的な工場を使って抽象的な部品を製造します。
このクラスでは具体的な部品、工場を一切使っていないことがポイントです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import abstractfactory.AbstractDrink; import abstractfactory.AbstractFactory; import abstractfactory.AbstractFood; public class Main { public static void main(String[] args) { final AbstractFactory factory = AbstractFactory.getFactory("listfactory.Factory"); final AbstractFood food = factory.createFood("ブラックサンダー"); final AbstractDrink drink = factory.createDrink("コカコーラ"); System.out.println(food.makeItem()); System.out.println(drink.makeItem()); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package factory; import abstractfactory.AbstractDrink; import abstractfactory.AbstractFactory; import abstractfactory.AbstractFood; public class Factory extends AbstractFactory{ @Override public AbstractFood createFood(final String name) { // TODO 自動生成されたメソッド・スタブ return new Food(name); } @Override public AbstractDrink createDrink(final String name) { // TODO 自動生成されたメソッド・スタブ return new Drink(name); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package factory; import abstractfactory.AbstractFood; public class Food extends AbstractFood { public Food(final String name) { super(name); } @Override public String makeItem() { return m_name + "は食品です。"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package factory; import abstractfactory.AbstractDrink; public class Drink extends AbstractDrink{ public Drink(final String name) { super(name); } @Override public String makeItem() { return m_name + "は飲み物です。"; } } |
以上のコードを実行すると以下のように出力されます。
1 2 |
ブラックサンダーは食品です。 コカコーラは飲み物です。 |
具体的な工場を新たに追加するのは簡単。
これが何を意味するかというと、
すでにどのようなクラスとメソッドを作れば良いかが明確になっているということです。
また具体的な工場を追加しても、抽象的な工場や、Main部分を修正する必要がないのです。