✏️ 스터디 모음집/디자인 패턴 스터디

디자인 패턴 스터디 기록 (5) - 팩토리 패턴, 의존성 역전

cocoroocoo 2022. 11. 2. 10:27

4. 객체지향 팩토리 패턴

이번장에서는 최대한 느슨한 결합으로 객체지향 디자인을 하는게 목표인 장입니다.

4-1. Simple Factory

예제 1)

Pizza orderPizza() {
	Pizza pizza = new Pizza();

	/* 이부분 */
	*if(type.equals("cheese")) {
		pizza = new CheesePizza();
	} else if (type.equals("greek")) {
		pizza = new GreekPizza();
	} else if (type.equals("pepperoni")) {
		pizza = new PepperoniPizza();
	}* 

	pizza.prepare();
	pizza.bake();
	pizza.cut();
	pizza.box();
	return pizza;
}

3가지인 피자라면 괜찮지만 여기서 몇가지의 피자가 더생긴다면 ?

계속해서 새로운 new 여러가지피자() 를 할 것인가

→ 팩토리를 만들자!

public class SimplePizzaFactory {
    public Pizza createPizza(String type) {
        Pizza pizza = null;

        if(type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("greek")) {
            pizza = new GreekPizza();
        } else if (type.equals("pepperoni")) {
            pizza = new PepperoniPizza();
        }

        return pizza;
    }
}

public class PizzaStore {
    SimplePizzaFactory factory;

    public PizzaStore(SimplePizzaFactory factory) {
        this.factory = factory;
    }

    public Pizza orderPizza(String type) {
        Pizza pizza;

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

4-2. 다양한 Factory

피자가게에서 체인점을 냈는데 지점마다 자기들만의 피자를 내고싶다

→ 지점마다 팩토리를 만들어서 해당 피자들을 찍어내면 된다!

예제1)

NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza("Veggle");

ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoStore.orderPizza("Veggie");

이렇게 했더니 여러 문제가 생겼음

→ 굽는방식이 여러가지가 생김 즉 팩토리마다 방식이 여러가지로 생겨서 관리가 용이하지 않음

→ 추상메소드를 만들어서 상속받아서 지점마다 해결하자가 이책에서 나온 해결 방법

public abstract class PizzaStore {
		// 추상 클래스
    public Pizza orderPizza(String type) {
        Pizza pizza;
        
        pizza = createPizza(type);

        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();

        return pizza;
    }

    abstract Pizza createPizza(String type);
		// 추상 메소드
}
public class NYPizzaStore extends PizzaStore {
    Pizza createPizza(String item) {
				// 추상 메소드를 상속 받아 작성
        if(type.equals("cheese")) {
            pizza = new NYStyleCheesePizza();
        } else if (type.equals("veggie")) {
            pizza = new NYStyleVeggiePizza();
        } else if (type.equals("pepperoni")) {
            pizza = new NYStylePepperoniPizza();
        }
    }
}

+@ // ChicagoPizzaStore extends PizzaStore
public class PizzaTestDrive {
    public static void main(STring[] args) {
        PizzaStore nyStore = new NYPizzaStore();
        PizzaStore chicagoStore = new ChicagoPizzaStore();

        Pizza pizza = nyStore.orderPizza("cheese");
				        

        pizza = chicagoStore.orderPizza("cheese");
    }

}

4-3 팩토리 메소드 패턴의 정의

팩토리 메소드 패턴에서는 객체를 생성할 때 필요한 인터페이스를 만들고
**어떤 클래스의 객체를 만들지는 서브클래스에 결정한다.**
즉 클래스 객체를 만드는 일을 서브클래스에서 주도적으로 행하는 패턴을 말함

4-4 객체 의존성 문제

이러면 제일 상위에 있는 팩토리 클래스가 엄청나게 의존성이 발생되는데 이에 따른 해결법으로 의존성 뒤집기를 이용한 추상 팩토리 패턴을 제안합니다.

헤드퍼스트책에서 지향 하는 의존성 뒤집기 원칙

  • new 를 사용하지 않고 Factory를 만들어서 변수에 저장하는 일을 방지
  • 추상 클래스 사용
  • 베이스 클래스에서 이미 구현되어 있는 메소드를 override 하지 않고 추상 메소드를 override 하자

4-5 추상 팩토리 패턴

public interface PizzaIngredientFactory {
    public Dough createDough();
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Calms createClam();
}
public Class NYPizzaIngredientFactory implements PizzaIngredientFactory {

    public Dough createDough() {}
    public Sauce createSacue() {}
    public Cheese createCheese() {}
    public Veggis[] createVeggies() {}
    public Pepperoni createPepperoni() {}
    public Clams createClam() {}
}
public class CheesePizza extends Pizza {
    PizzaIngredientFactory ingredientFactory;

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

    void prepare() {
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
        cheese = ingredientFactory.createCheese();
    }

}

4-6 정리

팩토리 메소드 패턴 - 클래스의 객체를 서브 클래스에서 결정

추상 팩토리 패턴 - 의존성을 해결하기 위해 객체로 이루어진 제품군을 생성하는 인터페이스를 제공하고 구상 클래스를 서브 클래스에서 만드는 것