1. 팩토리 메소드 패턴의 정의
객체를 생성하기 위한 인터페이스를 정의하고, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 한다.
단순한 팩토리 패턴?
다음과 같은 orderPizza 메소드가 있다고 할때 이 메소드는 pizza의 종류가 변경되면 코드가 변경되어야 한다. 따라서 변경되는 부분과 변경되지 않는 부분을 분리할 필요가 있다.
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 PepperoniPizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
다음과 같이 변경되는 부분을 새로운 SimplePizzaFactory라는 클래스도 분리하면 다음과 같다.
PizzaStore는 SimplePizzaFactory 를 이용하여 피자를 생성하고 이는 앞선 문제를 해결할 수 있다. (Spring 에서 Bean을 생성할 때 사용했던 방법과 매우 유사하다.)
public class SimplePizzaFactory {
public Pizza createPizza(String type){
Pizza pizza = null;
if(pizza.equals("cheese")) pizza = new CheesePizza();
if(pizza.equals("pepper")) pizza = new PepperoniPizza();
if(pizza.equals("clam")) pizza = new ClamPizza();
if(pizza.equals("veggie")) pizza = new VeggiePizza();
return pizza;
}
}
public class PizzaStore{
SimplePizzaFactory simplePizzaFactory;
public PizzaStore(SimplePizzaFactory simplePizzaFactory) {
this.simplePizzaFactory = simplePizzaFactory;
}
public Pizza orderPizza(String type){
Pizza pizza;
pizza = simplePizzaFactory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
하지만 뉴욕, 시카고등 지역별로 같은 피자여도 조금씩 다르게 만들기 원하는 상황에서는 어떤방법으로 해결하면 좋을까?
팩토리 메소드패턴
다음과 같이 PizzaStore를 추상클래스로 선언하고 기존 팩토리 클래스로부터 create하는 부분을 추상 메소드로 선언한다.
PizzaStore 추상 클래스
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); 추상 메소드
}
NYPizzaStore 클래스
public class NYPizzaStore extends PizzaStore{
@Override
public Pizza createPizza(String type){
Pizza pizza = null;
if(type.equals("cheese")) pizza = new NYStyleCheesePizza();
if(type.equals("peper")) pizza = new NYStylePepperoniPizza();
if(type.equals("clam")) pizza = new NYStyleClamPizza();
if(type.equals("veggie")) pizza = new NYStyleVeggiePizza();
return pizza;
}
}
Test클래스
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
Pizza nySytpePizza = nyStore.orderPizza("cheese");
System.out.println(nySytpePizza.getname());
}
}
전체적인 구조는 다음과 같다.
팩토리 메소드 패턴에서는 서브 클래스에서 어떤 클래스를 만들지 결정하게함으로서 (즉 추상클래스를 상속받은 NYPizzaStore에서 추상메소드를 수행함) 객체 생성을 캡슐화 한다.
이러한 팩토리 메소드 패턴에서 찾아볼 수 있는 객체 지향적 디자인 원칙은 의존성 뒤집기 이다.
기존 PizzaStore는 각 피자가 바뀔때마다 수정되어야하는 방식의 의존성을 가지고 있었으나.
PizzaStore -> NYStyleCheesePizza PizzaStore -> ChicagoStypeCheesePizza PizzaStore -> NYStyleVeggiePizza |
피자 인터페이스를 사용하여 인터페이스에만 의존적이고 나머지 실제 구현 객체는 인터페이스에 의존적인 관계가 되어 의존성 뒤집기 원칙을 가지고 있다.
PizzaStore -> Pizza Pizza <- NYStyleCheesePizza Pizza <- ChicagoStyleCheesePizza Pizza <- NYStyleVeggiePizza |
2. 추상 팩토리 패턴
피자를 만들기 위한 원재료를 처리하는 방법에 대해 고민해보자.
지역별 공장들을 추상화한 인터페이스를 가지는 구조로 작성한다
PizzaIngredientFactory 인터페이스
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClams();
}
NYPizzaIngredientFactory 클래스
public class NYPizzaingredientFactory implements PizzaIngredientFactory{
@Override
public Dough createDough() {
return new ThinCrustdough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
@Override
public Cheese createCheese() {
return new ReggianoCheese();
}
@Override
public Veggies[] createVeggies() {
Veggies veggies[] = { new Farlic(), new Onion(), new Mushroom(), new RedPepper() };
return veggies;
}
@Override
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
@Override
public Clams createClams() {
return new Freshclams();
}
}
전체적인 구조는 다음과 같다
3. 팩토리 메소드 패턴과 추상 팩토리의 차이?
- 팩토리 메소드 패턴은 상속, 추상 팩토리는 인터페이스를 이용한다.
- 팩토리 메소드 패턴은 단일 메소드가 여러 객체를 생성한다.
- 추상 팩토리 패턴은 여러 메소드에서 여러 객체를 생성하여 하나의 제품군처럼 만들어서 사용(create 도우, 치즈, 버섯 = 뉴욕 공장)
'프로그래밍 > 시큐어코딩' 카테고리의 다른 글
[디자인 패턴] 어댑터 패턴 (0) | 2020.07.14 |
---|---|
[디자인 패턴] 커맨드 패턴 (0) | 2020.07.13 |
[디자인 패턴] 옵저버 패턴 (0) | 2020.07.13 |
[스프링 이해와 원리] 프록시패턴, 데코레이터패턴이란? (0) | 2020.07.09 |
[스프링 이해와 원리] AOP란? (0) | 2020.07.09 |