추상 팩토리
상세화된 서브클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기 위한 인터페이스를 제공
활용성
- 객체가 생성되거나 구성·표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때
- 여러 제품군 중 하나를 선택해서 시스템을 설정해야 하고 한번 구성한 제품을 다른 것으로 대체할 수 있을 때
- 관련된 제품 객체들이 함께 사용되도록 설계되었고, 이 부분에 대한 제약이 외부에도 지켜지도록 하고 싶을 때
- 제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출시키고 싶을 때
public interface AbstractProductA {
}
class ProductA1 implements AbstractProductA {
}
class ProductA2 implements AbstractProductA{
}
public interface AbstractProductB {
}
class ProductB1 implements AbstractProductB {
}
class ProductB2 implements AbstractProductB {
}
public interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
class ConcreteFactory1 implements AbstractFactory {
public AbstractProductA createProductA() {
return new ProductA1();
}
public AbstractProductB createProductB() {
return new ProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
public AbstractProductA createProductA() {
return new ProductA2();
}
public AbstractProductB createProductB() {
return new ProductB2();
}
}
public class Client {
public static void main(String[] args) {
AbstractFactory factory = new ConcreteFactory1();
AbstarctProductA productA = factory.createProductA();
System.out.println("class=" + productA.getClass().getSimpleName();
//class=ProductA1
factory = new ConcreteFactory2();
productA = factory.createProductA();
System.out.println("class=" + productA.getClass().getSimpleName();
//class=ProductA2
}
}
똑같은 createProductA() 함수를 실행해도 Factory의 구현체에 따라 다른 클래스의 Product가 생성된다.
결과
- 구체적인 클래스를 분리합니다 : 응용프로그램이 생성할 객체의 클래스를 제어할 수 있다.
- 제품군을 쉽게 대체할 수 있도록 한다 : 구체 팩토리를 변경함으로써 응용프로그램은 서로 다른 제품을 사용할 수 있게 변경된다.
- 제품 사이의 일관성을 증진시킨다 : 하나의 군 안에 속한 제품들이 함께 동자하도록 설계되어 있을 때, 응용프로그램은 오직 한 군데에서 만든 객체를 사용함으로써 프로그램의 일관성을 갖게 한다.
- 새로운 종류의 제품을 제공하기 어렵다 : 새로운 제품을 추가하기 위해 기존 추상 팩토리(Abstract Factory)를 확장하기가 쉽지 않다. 새로운 종류의 제품이 등장하면 모든 구현 팩토리를 변경해야 한다.
구현
- 팩토리를 단일체(Singleton)로 정의한다 : 응용프로그램에서 한 제품군에 대해서 하나의 ConcreteFactory 인스턴스만 있으면 되므로, 단일체(Singleton)으로 구현하는 것이 바람직하다.
- 제품을 생성한다 : AbstractFactory는 단지 제품을 생성하기 위한 인터페이스를 선언하는 것이고, 그것을 생성하는 책임은 Product의 서브 클래스인 Concrete-Product(ProductA1, ProductA2, ...)에 있다. 이를 위한 가장 공통적인 방법은 각 제품을 위해서 팩토리 메서드를 정의하는 것이다.