피자 가게 클래스에는 여러가지 피자 객체를 직접 생성하는 클래스가 있다.
Pizza orderPizza(String type) {
Pizza pizza;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new PapperoniPizza();
}
pizza.bake();
pizza.box();
return pizza;
}
이 클래스의 문제점은, 피자 구상 클래스의 종류가 늘어날 때마다 코드를 수정해주어야 하는 부분이다.
피자 구상 클래스를 만들어주는 팩토리 클래스를 만들어보자.
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new PapperoniPizza();
}
return pizza;
}
}
Pizza orderPizza(String type) {
Pizza pizza = new SimplePizzaFactory().createPizza(type);
pizza.bake();
pizza.box();
return pizza;
이렇게 할 경우 피자 객체를 생성하는 모든 코드에서 피자 종류가 늘어나더라도 수정해야 할 필요가 없어지게 된다.
여러 종류의 피자 가게 (뉴욕 스타일, 시카고 스타일 등등)이 있을 경우, 각 피자 가게별로 조금씩 다른 차이점을 어떤 식으로 적용해야 할까?
위에서 만든 SimplePizzaFactory를 빼고 서로 다른 피자 팩토리 클래스를 만들어서 피자 가게 클래스에 주입시켜주면 되지 않을까?
NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza("cheese");
다음과 같은 방법도 사용할 수 있다.
피자 팩토리와 피자 스토어를 하나로 묶고, 공통 로직을 넣은 후, 피자 생성 부분만 구현하도록 하는 것이다.
public abstract class PizzaStore {
Pizza orderPizza(String type) {
Pizza pizza = createPizza();
pizza.bake();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);
}
피자 가게 추상 클래스 안에 createPizza 추상 메서드를 만들고, 각 피자 분점 구상 클래스에서 해당 메서드를 구현하는 방식이다.
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (item.equals("greek")) {
return new NYStyleGreekPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePapperoniPizza();
} else {
return null;
}
}
}
위와 같은 방식을 팩토리 메서드 패턴이라고 한다.