팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 만든다.
팩토리 메소드 패턴을 통해 클래스의 인스턴스를 만드는 일을 서브클래스에 맡길 수 있다.
객체지향의 팩토리 개념이 없이 피자가게를 만든다고 생각해보자
public class DependentPizzaStore {
public Pizza createPizza(String style, String type) {
Pizza pizza = null;
//뉴욕풍 피자를 처리하는 부분
if (style.equals("NY")) {
if (type.equals("cheese")) {
pizza = new NYStyleCheesePizza();
}
else if (type.equals("veggie")) {
pizza = new NYStyleVeggiePizza();
}
else if (type.equals("clam")) {
pizza = new NYStyleClamPizza();
}
else if (type.equals("pepperoni")) {
pizza = new NYStylePepperoniPizza();
}
//시카고풍 피자를 처리하는 부분
} else if (style.equals("Chicago")) {
if (type.equals("cheese")) {
pizza = new ChicagoStyleCheesePizza();
}
else if (type.equals("veggie")) {
pizza = new ChicagoStyleVeggiePizza();
}
else if (type.equals("clam")) {
pizza = new ChicagoStyleClamPizza();
}
else if (type.equals("pepperoni")) {
pizza = new ChicagoStylePepperoniPizza();
}
} else {
System.out.println("Error: invalid type of pizza");
return null;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
위 소스의 객체 의존성의 다이어그램으로 그려보면 다음과 같습니다
SOLID 원칙의 D에 해당하는 의존 역전의 원칙을 적용하여 구상 클래스에 대한 의존성을 줄이는것이 좋다는 것이 좋다는것을 알고 있을 것이다.
"고수준" 구성요소는 다른 "저수준" 구성요소에 의해 정의되는 행동이 들어있는 구성요소
- 고수준: PizzaStore class
PizzaStore는 다양한 피자 객체를 만들고, 피자를 준비, 굽고, 자르고, 포장
PizzaStore에서 행동은 피자의 의해 정의- 저수준: Pizza class
public interface PizzaIngredientFactory {
//각 재료별로 생성 메소드 정의.
public abstract Dough createDough();
public abstract Sauce createSauce();
public abstract Cheese createCheese();
public abstract Veggies[] createVeggies();
public abstract Pepperoni createPepperoni();
public abstract Clams createClam();
}
//========================================================================
//모든 재료 공장에서 구현해야 하는 인터페이스를 구현
//========================================================================
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() {
Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
public abstract class Pizza {
String name;
String dough;
String sauce;
Veggies veggies[];
Cheese cheess;
Pepperoni pepperoni;
Clams clam;
abstract void prepare();
void bake() {
System.out.println("Bake for 25 miutes at 350");
}
void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
void box() {
System.out.println("Place pizza in official PizzaStore box");
}
public String getName() {
return name;
}
String getName(){
return name;
}
public String toString() {
//피자 이름 출력
}
}
뉴욕 피자 클래스와 시카고 피자 클래스의 차이점을 무엇일까?
이들은 다른 재료를 사용하는 것 빼면 다른 점이 없다.
따라서, 원재료 공장을 통해 다른 재료를 준비한다면 지역별로 따로 클래스를 만들 필요가 없다.
pulic class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {
System.out.println("Preparing " + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
public abstract class PizzaStore{
public Pizza orderPizza(String type){
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza (String type);
}
public class NYPizzaStore extends PizzaStore{
protected Pizza createPizza(String item){
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new NYPizzaStoreIngredientFactory();
if (item.equls("chesse")){
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza);
} else if (item.equls("veggie")){
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("New York Style Veggie Pizza);
} else if (item.equls("clam")){
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza);
} else if (item.equls("pepperoni")){
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("New York Style Pepperoni Pizza);
}
return pizza;
}
헤드퍼스트 디자인패턴, 한빛미디어, 에릭 프리먼, 엘리자베스 프리먼, 케이시 시에라, 버트 베이츠 저