1. 간단한 팩토리


팩토리 메서드 패턴과 추상 팩토리 패턴을 알아보기 전에 우선, 팩토리가 무엇인지를 알아야합니다.
팩토리는 객체 생성을 처리하는 클래스를 일컫습니다.

아래 코드에서 객체를 생성하는 부분이 if~ else if 로 하드코딩되어 있는데, 이 부분을 팩토리로 뺄 수 있습니다.

public class PizzaStore {
Pizza orderPizza(String type) {
Pizza pizza;
// 아래 부분이 구체적인 객체를 생성하는 부분입니다.
// 객체를 생성하는 부분은 새로운게 추가되거나 없어지는 등 언제든 변할 수 있습니다.
if (type.equals("cheese")) pizza = new CheesePizza();
else if (type.equals("greekPizza")) pizza = new GreekPizza();
else if (type.equals("pepperoni")) pizza = new PepperoniPizza();
// 아래 부분은 변하지 않는 부분으로 볼 수 있습니다.
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
public interface Pizza {
void prepare(); // 피자 만들 준비
void bake(); // 피자 굽기
void cut(); // 피자 커팅
void box(); // 다 만든 피자 박스에 담기
}
public CheesePizza implements Pizza { ... }
public GreekPizza implements Pizza { ... }
public PepperoniPizza implements Pizza { ... }

 

 

피자 종류가 늘어날 때마다 위에서 else if문을 추가해줘야할까요?
이럴 때, 객체 생성을 처리하는 간단한 팩토리를 만들어 객체 생성을 분리할 수 있습니다.

public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) pizza = new CheesePizza();
else if (type.equals("greekPizza")) pizza = new GreekPizza();
else if (type.equals("pepperoni")) pizza = new PepperoniPizza();
return pizza;
}
}

 

이제 위 팩토리를 사용하면 처음에 봤던 코드는 다음과 같은 모양을 가질 수 있습니다.

public class PizzaStore {
SimplePizzaFactory factory = new SimplePizzaFactory();
Pizza orderPizza(String type) {
Pizza pizza = factory.createPizza(type);
// 아래 부분은 변하지 않는 부분으로 볼 수 있습니다.
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
public interface Pizza {
void prepare(); // 피자 만들 준비
void bake(); // 피자 굽기
void cut(); // 피자 커팅
void box(); // 다 만든 피자 박스에 담기
}
public CheesePizza implements Pizza { ... }
public GreekPizza implements Pizza { ... }
public PepperoniPizza implements Pizza { ... }

2. 팩토리 메서드 패턴


위처럼 객체 생성을 위해 별도의 팩토리 클래스를 만들 수도 있지만, 메서드로도 만들어 줄 수 있습니다.
아래 코드를 보면 `createPizza()` 라는 추상 메서드를 두었고, 이 메서드는 객체 생성을 담당하는 팩토리 메서드입니다.
(팩토리라는 용어가 객체 생성과 동일한 의미라고 이해하시면 됩니다.)

public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type); // type에 대한 구체적인 피자 객체를 생성해서 반환한다.
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
// 객체 생성을 담당하는 팩토리 메서드를 추상 메서드로 정의한다.
public abstract Pizza createPizza(String type);
}
public interface Pizza {
void prepare(); // 피자 만들 준비
void bake(); // 피자 굽기
void cut(); // 피자 커팅
void box(); // 다 만든 피자 박스에 담기
}
public CheesePizza implements Pizza { ... }
public GreekPizza implements Pizza { ... }
public PepperoniPizza implements Pizza { ... }

 

즉, 객체 생성을 서브 클래스에 위임한다는 의미인데요,
이제 PizzaStore를 상속받는 구상(Concrete) PizzaStore 클래스를 살펴보겠습니다.

public class NYPizzaStore extends PizzaStore {
public Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {
pizza = new CheesePizza();
} else if ("pepperoni".equals(type)) {
pizza = new PepperoniPizza();
}
return pizza;
}
}

3. 추상 팩토리 패턴


 

추상 팩토리는 처음에 살펴봤던 팩토리를 추상화한거라고 이해하면 됩니다.
팩토리 메서드가 완전한 하나의 제품을 생성하기 위한 용도라면, 추상 팩토리는 제품군(일련의 재료들)을 생성하기 위한 용도입니다. 

public class NYPizzaStore extends PizzaStore {
// 피자에는 빵, 도우, 치즈, 소스 등 여러가지 재료들이 있을 겁니다.
// 어떤 스타일의 재료들을 사용할지를 정해야 할텐데, 이때 아래의 추상 팩토리가 사용됩니다.
ProductFactory factory = NYProductFactory();
public Pizza createPizza(String type) {
Pizza pizza = null;
if ("cheese".equals(type)) {
// Concrete Pizza 객체를 생성하면서 추상 팩토리를 넘깁니다.
pizza = new CheesePizza(factory);
} else if ("pepperoni".equals(type)) {
pizza = new PepperoniPizza(factory);
}
return pizza;
}
}

 

 

 

댓글

댓글을 사용할 수 없습니다.