Abstract Factory

abstract-factory.png

難しい言葉でいうと、
互いに関連したり依存しあうオブジェクト群を、その具象クラスを明確にせずに生成するためのインタフェースを提供する
具象クラスを指定することなく、一連の関連オブジェクトや依存オブジェクトを作成するためのインタフェースを提供します[2]

これがAbstract Factoryクラスだ!

package factory.ingredients;
public interface PizzaIngredientFactory {
    public Dough createDough();//Doughはベースクラス。インスタンスは、薄いカリカリの生地かもしれないし、厚くてフワフワの生地かもしれない。
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();
}
派生クラスその1
ニューヨーク用の材料を作る工場
派生クラスその1
シカゴ用の材料を作る工場
package factory.ingredients;
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
    @Override
    public Dough createDough() {
        return new ThinCrustDough();//薄くてカリカリの生地
    }
    @Override
    public Sauce createSauce() {
        return new MarinaraSauce();
    }
    @Override
    public Cheese createCheese() {
        return new ReggianoCheese();
    }
    @Override
    public Veggies[] createVeggies() {
        Veggies veggies[]={new Garlic(),new Onion(),new Mushroom(),new RedPepper()};
        return veggies;
    }
 
    @Override
    public Pepperoni createPepperoni() {
        return new SlicedPepperoni();
    }
    @Override
    public Clams createClam() {
        return new FreshClams();
    }
 
}
package factory.ingredients;
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {
    @Override
    public Dough createDough() {
        return new ThickCrustDough();//厚い生地
    }
    @Override
    public Sauce createSauce() {
        return new PlumTomatoSauce();
    }
    @Override
    public Cheese createCheese() {
        return new MozzarellaCheese();
    }
    @Override
    public Veggies[] createVeggies() {
        Veggies veggies[]={    new BlackOliees(),
                            new Spinach(),
                            new Eggplant()};
        return veggies;
    }
    @Override
    public Pepperoni createPepperoni() {
        return  new SlicedPepproni();
    }
    @Override
    public Clams createClam() {
        return new FrozenClams();
    }
}

どんな風に良くなったのか?

ダメな例
ものすごく多種多様なクラスが発生している。
複雑で、頭がこんがらがっちゃうようなifとswitchの応酬!!
新たに材料作る用の工場クラスを作ることにより、
すべて同じなんとかPizza()クラスでローカライズすることができた。
package factory;
//非常に依存関係の多いPizzaStore
public class DependentPizzaStore {
    public Pizza createPizza(String style,String type){
        Pizza pizza=null;
        if(style.equals("ニューヨーク")){
            if(type.equals("チーズ")){
                pizza=new NYStyleCheesePizza();
            }else if(type.equals("野菜")){
                pizza=new NYStyleVeggiePizza();
            }else if(type.equals("クラム")){
                pizza=new NYStyleClamPizza();
            }else if(type.equals("ペパロニ")){
                pizza=new NYStylePepperoniPizza();
            }
        }else if(style.equals("シカゴ")){
            if(type.equals("チーズ")){
                pizza=new ChicagoStyleCheesePizza();
            }else if(type.equals("野菜")){
                pizza=new ChicagoStyleVeggiePizza();
            }else if(type.equals("クラム")){
                pizza=new ChicagoStyleClamPizza();
            }else if(type.equals("ペパロニ")){
                pizza=new ChicagoStylePepperoniPizza();
            }
        }else{
            System.out.println("無効なピザの種類");
            return null;
        }
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
 
}
ニューヨークピザ店クラス
package factory;
 
import factory.ingredients.NYPizzaIngredientFactory;
import factory.ingredients.PizzaIngredientFactory;
 
public class NYPizzaStore extends PizzaStore {
 
    @Override
    protected Pizza createPizza(String type) {
        Pizza pizza=null;
        PizzaIngredientFactory ingredientFactory=new NYPizzaIngredientFactory();
        if(type.equals("チーズ")){
            pizza=new CheesePizza(ingredientFactory);
            pizza.setName("ニューヨークスタイルチーズピザ");
        }else if(type.equals("野菜")){
            pizza=new VeggiePizza(ingredientFactory);
            pizza.setName("ニューヨークスタイル野菜ピザ");
        }else if(type.equals("クラム")){
            pizza=new ClamPizza(ingredientFactory);
            pizza.setName("ニューヨークスタイルクラムピザ");
        }else if(type.equals("クラム")){
            pizza=new PepperoniPizza(ingredientFactory);
            pizza.setName("ニューヨークスタイルペパロニピザ");
        }
        return null;
    }
 
}

シカコピザ店クラス
package factory;
import factory.ingredients.PizzaIngredientFactory;
public class ChicagoPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String type) {
        Pizza pizza=null;
        PizzaIngredientFactory ingredientFactory=new ChicagoPizzaIngredientFactory();
        if(type.equals("チーズ")){
            pizza=new CheesePizza(ingredientFactory);
            pizza.setName("シカゴスタイルチーズピザ");
        }else if(type.equals("野菜")){
            pizza=new VeggiePizza(ingredientFactory);
            pizza.setName("シカゴスタイル野菜ピザ");
        }else if(type.equals("クラム")){
            pizza=new ClamPizza(ingredientFactory);
            pizza.setName("シカゴスタイルクラムピザ");
        }else if(type.equals("ペパロニ")){
            pizza=new PepperoniPizza(ingredientFactory);
            pizza.setName("シカゴスタイルペパロニピザ");
        }
        return null;
    }
 
}

ローカライズした材料に対応できるCheecePizzaクラス
package factory;
 
import factory.ingredients.PizzaIngredientFactory;
 
public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;//これはインタフェース
    public CheesePizza(PizzaIngredientFactory ingredientFactory){
        this.ingredientFactory=ingredientFactory;
    }
    @Override
    void prepare() {
        System.out.println(name+"を下処理");
        dough=ingredientFactory.createDough();
        sauce=ingredientFactory.createSauce();
        cheese=ingredientFactory.createCheese();
        clam=ingredientFactory.createClam();
    }
 
}

abstract

サポートサイト Wikidot.com abstract