디자인패턴 중에서 생성 패턴(Creational Pattern)의 대표적인 패턴들이다.

팩토리 패턴의 종류

  • 팩토리 메서드(Factory Method) 패턴
  • 추상 팩토리(Abstract Factory) 패턴

시작하기전에

디자인 패턴에 포함되지는 않지만, 팩토리 패턴의 기본이 되는 팩토리 구조에 대해서 알아보자.

팩토리를 사용하는 이유

클라이언트에서 사용할 객체를 생성하는 부분을 캡슐화하여 느슨한 결합 상태로 만들어, 변화에는 닫혀있고 확장에는 열려있는 코드를 만들 수 있다.

변경 전의 코드

// 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;
}

변경 후의 코드

// Pizza 클래스의 생성을 전담하는 클래스 = 팩토리
public class SimplePizzaFactory {
  public Pizza createPizza(String type) {
    Pizza = null;

    if (type.equals("cheese")) {
      pizza = new CheesePizza();
    } else if (type.equals("greek")) {
      pizza = new GreekPizza();
    } else if (type.equals("pepperoni")) {
      pizza = new PepperoniPizza();
    }

    return pizza;
  }
}
SimplePizzaFactory factory = new SimplePizzaFactory();

// Pizza 객체의 생성은 팩토리에 맞기고 사용에 전념하는 메서드
Pizza orderPizza(String type) {
  Pizza pizza;

  pizza = factory.createPizza(type);

  pizza.prepare();
  pizza.bake();
  pizza.cut();
  pizza.box();

  return pizza;
}

클래스 다이어그램

팩토리

##팩토리 메소드 (Factory Method)

객체를 생성하는 인터페이스를 정의하지만, 인스턴스를 만들 클래스의 결정은 서브클래스가 한다. Factory Method 패턴에서는 클래스의 인스턴스를 만드는 시점을 서브클래스로 미룬다.

GoF의 디자인 패턴

구조

팩토리 메소드

팩토리 메소드 패턴에서는 서브클래스에서 어떤 클래스를 만들지 결정하게 함으로써 객체 생성을 캡슐화한다.

public abstract class PizzaStore {
  // 실제 객체의 생성이 일어날 추상 메서드 (서브 클래스에 객체의 생성의 위임)
  abstract Pizza createPizza(String item);

  public Pizza OrderPizza(String type) {
    Pizza pizza = createPizza(type);

    pizza.prepare();
    pizza.bake();
    pizza.cut();
    pizza.box();

    return pizza;
  }
}
// 객체의 생성을 위임 받은 서브 클래스
public class NYPizzaStore extends PizzaStore {
  Pizza createPizza(String item) {
    if (item.equals("cheese")) {
      return new NYStyleCheesePizza();
    } else if (item.equals("veggie")) {
      return new NYStyleVeggiePizza();
    } else if (item.equals("clam")) {
      return new NYStyleClamPizza();
    } else if (item.equals("pepperoni")) {
      return new NYStylePepperoniPizza();
    } else return null;
  }
}

클래스 다이어그램

팩토리메소드 예제 다이어그램

##추상 팩토리 (Abstract Factory)

구체적인 클래스를 지정하지 않고 관련성을 갖는 객체들의 집합을 생성하거나 서로 독립적인 객체들의 집합을 생성할 수 있는 인터페이스를 제공한다.

GoF의 디자인 패턴

구조

추상 팩토리

public class NYPizzaStore extends PizzaStore {

  protected Pizza createPizza(String item) {
    Pizza pizza = null;

    // 팩토리 객체
    PizzaIngredientFactory ingredientFactory =
      new NYPizzaIngredientFactory();

    if (item.equals("cheese")) {
      // 생성된 팩토리 객체를 함께 전달하여 내부에서 재료클래스의 객체를 생성
      pizza = new CheesePizza(ingredientFactory);
      pizza.setName("New York Style Cheese Pizza");
    } else if (item.equals("veggie")) {
      pizza = new VeggiePizza(ingredientFactory);
      pizza.setName("New York Style Veggie Pizza");
    } else if (item.equals("clam")) {
      pizza = new ClamPizza(ingredientFactory);
      pizza.setName("New York Style Clam Pizza");
    } else if (item.equals("pepperoni")) {
      pizza = new PepperoniPizza(ingredientFactory);
      pizza.setName("New York Style Pepperoni Pizza");
    }
    return pizza;
  }
}
// 추상 팩토리를 사용하는 클라이언트 역할을 수행
// Pizza 클래스는 도우, 소스, 치즈등의 재료 객체들의 집합
public class CheesePizza extends Pizza {
  // 재료의 인스턴스를 생성해주는 추상 팩토리
  PizzaIngredientFactory ingredientFactory;

  public CheesePizza(PizzaIngredientFactory ingredientFactory) {
    this.ingredientFactory = ingredientFactory;
  }

  void prepare() {
    // 객체들의 집합을 생성
    dough = ingredientFactory.createDough();
    sauce = ingredientFactory.createSauce();
    cheese = ingredientFactory.createCheese();
  }
}
// Abstract Factory
public interface PizzaIngredientFactory {
  public Dough createDough();
  public Sauce createSauce();
  public Cheese createCheese();
  public Veggies[] createVeggies();
  public Pepperoni createPepperoni();
  public Clams createClam();
}
// ConcreteFactory1
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();
  }
}
// AbstractProductA
public interface Cheese {
  public String toString();
}
// ConcreteProductA1
public class ReggianoCheese implements Cheese {
  public String toString() {
    return "Reggiano Cheese";
  }
}

클래스 다이어그램

팩토리메소드 예제 다이어그램