m1ndy5's coding blog

추상 팩토리 패턴(Abstract Factory Pattern) 본문

백엔드 with java/Design Pattern

추상 팩토리 패턴(Abstract Factory Pattern)

정민됴 2023. 11. 26. 20:09

추상 팩토리 패턴 정의

연관성이 있는 객체 군이 여러개 있을 경우 이들을 묶어 추상화하고, 어떤 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화 하는 생성 패턴 -> 다양한 구성 요소 별로 '객체의 집합'을 생성해야 할 때 유용

원재료 팩토리 만들기

피자를 만들 때 들어가는 토핑이 조금씩 다르다고 생각해보자.
일단 각 재료를 공급하는 Factory를 만들어보자

public interface PizzaIngredientFactory{
    public Dough createDough();
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
}

이 안의 메소드를 전부 추상으로 만든 이유는 각 스토어에서 쓰는 재료의 종류가 다를 것이기 때문이다.
예를들어 어떤 곳은 토마토 소스를 쓰고 어떤 곳은 크림 소스를 쓰고 이런식으로
그럼 이제 각 지역의 재료 팩토리를 구현해보자

public class NYPizzaIngredientFactory implements PizzaIngredientFactory{
    public Dough createDough(){
        return new ThinCrustDough();
    }

    public Sauce createSauce(){
        return new MarinaraSauce();
    }

    public Cheese createCheese(){
        return new ReggianoCheese();
    }

    public Veggies[] createVeggies(){
        return {new Garlic(), new Onion()};
    }
}

다른 지역 IngredientFactory는 다른 재료의 구상클래스로 이루어질 것이다.
이 재료들로 이루어진 Pizza 추상 클래스를 만들어 보자

public abstract class Pizza{
    Dough dough;
    Sauce sauce;
    Veggies veggies[];
    Cheese cheese;

    // 피자에 필요한 재료들을 가져오는 추상 메소드
    abstract void prepare();

}
public class CheesePizza extends Pizza{
    PizzaIngredientFactory ingredientFactory;

    public CheesePizza(PizzaIngredientFactory ingredientFactory){
        this.ingredientFactory = ingredientFactory;
    }

    @Override
    void prepare(){
        dough = ingredinentFactory.createDough();
        sauce = ingredinentFactory.createSauce();
        cheese = ingredinentFactory.createCheese();
    }
}

이제 이렇게 만든 치즈 피자를 NYPizzaStore에서 만들어보자

public class NYPizzaStore extends PizzaStore{
    protected Pizza createPizza(String item){
        Pizza pizza;
        PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();

        if(item.equals("Cheese")){
            pizza = new CheesePizza(ingredientFactory);
        }
    }
}

public class Main{
    public static void main(String[] args){
        PizzaStore pizzaStore = new NYPizzaStore();

        // NYPizzaStore은 NYPizzaIngredientFactory의 재료를 사용하기 때문에 NYPizzaIngredientFactory의 재료로 만들어진 CheesePizza가 만들어지게 된다.
        Pizza pizza = pizzaStore.orderPizza("Cheese");
    }
}

팩토리 메소드 패턴 VS 추상 팩토리 패턴

팩토리 메서드 예시

PizzaStore라는 Pizza를 생산하는 데 필요한 추상 인터페이스를 제공

NYPizzaStore과 ChicagoPizzaStore과 같은 각 서브클래스에서 어떤 클래스의 인스턴스를 만들지 결정

createPizza()가 팩토리 메서드였음

Pizza라는 추상 클래스를 구현한 다양한 피자들이 각 store의 createPizza()에서 만들어짐

추상 팩토리 예시

PizzaIngredientFactory라는 제품군(원재료들)을 생산하는 추상 인터페이스를 제공

NYPizzaIngredientFactory와 ChicagoPizzaIngredientFactory같은 서브클래스에서 제품군을 생산함

Dough의 종류, Clams의 종류 등 다양한 제품군을 결정할 수 있음

또한 추상팩토리에서 팩토리 메소드를 사용할 수 있음