팩토리 메서드란?
- 객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스가 내리도록 하는 패턴
- 팩토리 메소드란 쉽게 말하면 객체를 생성 반환하는 메서드이다.
- 다시 말해서 팩토리메서드 패턴이란 하위 클래스에서 팩토리 메서드를 오버라이딩해서 객체를 반환하게 하는 패턴이다.
어떤 상황에서 주로 사용하는가?
- 어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때
- 생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때
- 객체 생성의 책임을 몇 개의 보조 서브클래스 가운데 하나에게 위임하고, 어떤 서브클래스가 위임자인지에 대한 정보를 국소화시키고 싶을 때
구조 & 참여자
Product
- 팩토리 메서드가 생성하는 객체의 인터페이스 정의한다.
ConcreteProduct
- Product 클래스에 정의된 인터페이스를 실제로 구현하는 클래스
Creator
- Product 타입의 객체를 반환하는 팩토리 메서드를 선언하는 클래스
- 팩토리 메서드를 기본적으로 구현, ConcreteProduct 객체를 반환한다.
- Product 객체의 생성을 위해 팩토리 메서드를 호출한다.
ConcreteCreator
- 팩토리 메서드를 재정의하여 ConcreteProduct의 인스턴스를 반환
구현시 고려할 점
팩토리 메소드 페턴의 구현 방법은 크게 두 가지가 있다.
- Creator를 추상 클래스로 정의하고, 팩토리 메소드는 abstract로 선언하는 방법
- Creator가 구체 클래스이고, 팩토리 메소드의 기본 구현을 제공하는 방법
팩토리 메소드의 인자를 통해 다양한 Product를 생성하게 한다.
- 팩토리 메소드에 잘못된 인자가 들어올 경우의 런타임 에러 처리에 대해 고민할 것.
- Enum 등을 사용하는 것도 고려할 필요가 있다.
장점과 단점
장점
- 팩토리 메서드 패턴은 응용프로그램에 국한된 클래스가 코드에 종속되지 않도록 해준다
- 응용프로그램은 Product 클래스에 정의된 인터페이스와만 동작하도록 코드가 만들어지기 때문에, 사용자가 정의한 어떤 ConcreteProduct 클래스가 와도 동작할 수 있다.
- SRP
- OCP
단점
패턴 예제
interface Pizza {
void prepare();
void bake();
void box();
}
class NYStyleCheesePizza implements Pizza { ... }
class NYStylePepperoniPizza implements Pizza { ... }
abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);
}
class NYPizzaStore extends PizzaStore {
@Override
Pizza createPizza(String type) {
if ("cheese".equals(type)) {
return new NYStyleCheesePizza();
} else if ("pepperoni".equals(type)) {
return new NYStylePepperoniPizza();
}
return null;
}
class ChicagoPizzaStore extends PizzaStore {
@Override
Pizza createPizza(String type) {
if ("cheese".equals(type)) {
return new ChicagoStyleCheesePizza();
} else if ("pepperoni".equals(type)) {
return new ChicagoStylePepperoniPizza();
}
return null;
}
}
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
Pizza pizza1 = chicagoStore.orderPizza("pepperoni");
- Creator는 자신의 서브클래스를 통해 실제 필요한 팩토리 메서드를 정의하여 적절한 ConcreteProduct의 인스턴스를 반환할 수 있게 한다.
참고 문헌 및 출처