[디자인 패턴] 팩토리 메소드 패턴 :: 잡다한 프로그래밍
반응형

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. 팩토리 메소드 패턴과 추상 팩토리의 차이?

  1. 팩토리 메소드 패턴은 상속, 추상 팩토리는 인터페이스를 이용한다.
  2. 팩토리 메소드 패턴은 단일 메소드가 여러 객체를 생성한다.
  3. 추상 팩토리 패턴은 여러 메소드에서 여러 객체를 생성하여 하나의 제품군처럼 만들어서 사용(create 도우, 치즈, 버섯 = 뉴욕 공장)
반응형

+ Recent posts