📌 추상 팩토리 패턴(Abstract Factory Pattern) 이란?
연관성이 있는 객체 군이 여러 개 있을 경우 이들을 묶어 추상화하고, 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화하는 생성 패턴이다.
추상 팩토리 패턴은 상세화된 서브 클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기 위한 인터페이스를 제공한다.
클라이언트에서 특정 객체를 사용할 때 팩토리 클래스만을 참조하여 특정 객체에 대한 구현부를 감추어 역할과 구현을 분리시킬 수 있다.
예를 들어 모니터, 마우스, 키보드를 묶은 전자 제품군이 있고, 이들 안에서 또 삼성, 애플, 로지텍 등 집합이 브랜드 명으로 나뉠 때 복잡하게 묶이는 제품군들을 관리와 확장하기 용이하게 패턴화 한 것이 추상 팩토리 패턴이다.
📌 추상 팩토리 패턴 구조
[ AbstractFactory ]
최상위 공장 클래스이다. 여러 개의 제품들을 생성하는 메서드들을 추상화한다.
[ ConcreteFactory ]
서브 공장 클래스이다. 타입에 맞는 제품 객체들을 반환하도록 메서드들을 오버라이딩한다.
[ AbstractProduct ]
각 타입의 제품들을 추상화한 인터페이스이다.
[ ConcreteProduct ]
각 타입의 제품 구현체들이다. 팩토리 객체로부터 생성된다.
[ Client ]
클라이언트는 추상화된 인터페이스만을 사용하기 때문에 구체적인 제품, 공장에 대해서는 모른다.
📌 팩토리 메서드 패턴과의 공통점 / 차이점
[ 공통점 ]
- 객체 생성의 책임 분리
- 두 패턴 모두 객체 생성을 클라이언트로부터 분리하여 객체 생성의 책임을 서브 클래스 또는 구체적인 구현 클래스로 위임한다.
- 인터페이스 기반
- 추상 클래스 또는 인터페이스를 사용하여 객체 생성에 대한 통일된 인터페이스를 제공한다.
- 이를 통해 클라이언트는 구체 클래스의 세부 사항을 모르고도 객체를 생성할 수 있다.
[ 차이점 ]
- 목적
- 팩토리 메서드 패턴
- 객체 생성 이후의 처리에 중점을 두며 서브 클래스에서 어떤 클래스의 인스턴스를 생성할지 결정한다.
- 추상 팩토리 패턴
- 여러 종류의 관련된 객체 집합을 생성하고, 이들을 함께 사용할 수 있도록 인터페이스를 제공한다.
- 팩토리 메서드 패턴
- 단일 제품 vs 제품군
- 팩토리 메서드 패턴
- 주로 하나의 제품에 중점을 둔다.
- 추상 팩토리 패턴
- 여러 종류의 제품 군에 중점을 둔다.
- 팩토리 메서드 패턴
- 클라이언트의 관점
- 팩토리 메서드 패턴
- 클라이언트는 하나의 메서드를 호출하여 객체를 생성하며, 하위 클래스에서 구체적인 클래스를 결정한다.
- 추상 팩토리 패턴
- 클라이언트는 여러 메서드를 호출하여 객체 군을 생성하며, 팩토리를 선택하여 해당하는 제품 군을 생성한다.
- 팩토리 메서드 패턴
- 확장성
- 팩토리 메서드 패턴
- 객체의 생성에 대한 확장이 상대적으로 용이하다.
- 추상 팩토리 패턴
- 새로운 제품이나 제품 군을 추가할 때마다 팩토리와 제품 클래스를 모두 추가해야 하므로 상대적으로 확장성이 떨어진다.
- 팩토리 메서드 패턴
📌 추상 팩토리 패턴 구현 방법
[ 제품군 ]
// A 제품군
public interface AbstractProductA {
}
public class ConcreteProductA_1 {
}
public class ConcreteProductA_2 {
}
// B 제품군
public interface AbstractProductB {
}
public class ConcreteProductB_1 {
}
public class ConcreteProductB_2 {
}
[ 공장 ]
public interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// 1번 제품군을 생산하는 공장
public class ConcreteFactoryNo1 implements AbstractFactory {
public AbstractProductA createProductA() {
return new ConcreteProductA_1();
}
public AbstractProductB createProductB() {
return new concreteProductB_1();
}
}
// 2번 제품군을 생산하는 공장
public class ConcreteFactoryNo2 implements AbstractFactory {
public AbstractProductA createProductA() {
return new ConcreteProductA_2();
}
public AbstractProductB createProductB() {
return new ConcreateProductB_2();
}
}
[ 클라이언트 ]
public class Client {
public static void main(String[] args) {
AbstractFactory factory;
// 공장 1번 가동
factory = new ConcreteFactoryNo1();
AbstractProductA productA_1 = factory.createProductA();
// 공장 2번 가동
factory = new ConcreteFactoryNo2();
AbstractProductA productA_2 = factory.createProductA();
}
}
📌 추상 팩토리 패턴 사용 상황
[ 여러 제품 군이 존재하는 경우 ]
시스템이 여러 제품 군을 가지고 있고, 각 군에 속하는 객체들을 함께 사용해야 할 때 추상 팩토리 패턴이 유용하다.
GUI 라이브러리에서는 버튼, 텍스트 상자, 체크 박스 등이 각각의 제품 군을 형성할 수 있다.
[ 제품군 간의 일관성 유지가 필요한 경우 ]
서로 다른 제품 군 간에 일관성을 유지하고 싶을 때 추상 팩토리 패턴이 도움이 된다.
애플리케이션에서 두 가지 다른 테마(라이트 모드, 다크 모드)를 지원하면서 각 테마에 따른 버튼, 텍스트 상자 등의 객체를 생성할 수 있다.
[ 제품 군의 추가 및 확장이 가능한 경우 ]
새로운 제품이나 제품 군을 추가하고, 기존 코드의 영향을 미치지 않으면서 확장하고자 할 때 추상 팩토리 패턴이 효과적이다.
새로운 팩토리와 제품 클래스를 추가하여 시스템을 확장할 수 있다.
[ 클라이언트가 구체적인 클래스를 몰라도 되는 경우 ]
클라이언트는 추상 팩토리의 인터페이스만을 사용하여 객체를 생성하므로 실제 구체적인 클래스에 대한 지식이 없어도 된다.
이는 유지보수와 확장성을 높일 수 있다.
📌 추상 팩토리 패턴의 장 / 단점
[ 장점 ]
- 객체 군의 일관성 유지
- 추상 팩토리 패턴은 한 번에 여러 제품 객체를 생성하므로 일관성을 유지하기가 용이하다.
- 유연성 및 확장성
- 새로운 제품이나 제품 군을 추가하는 것이 비교적 쉽다.
- 새로운 팩토리와 제품 클래스를 추가하여 시스템을 확장할 수 있다.
- 클라이언트 코드 분리
- 클라이언트 코드는 추상 팩토리의 인터페이스만 알고 있으면 된다.
- 실제 구현 클래스에 대한 지식이 없어도 되므로 시스템을 유연하게 확장하고 변경할 수 있다.
- 단일 책임 원칙 준수
- 팩토리 클래스는 한 가지 종류의 객체만 생성하는데 집중하므로 단일 책임 원칙을 준수한다.
[ 단점 ]
- 복잡성 증가
- 각 구현체마다 팩토리 객체들을 모두 구현해주어야 하기 때문에 객체가 늘어날때 마다 클래스가 증가하여 복잡성이 증가한다.
- 제품 군이 복잡하고 제품들 사이의 관계가 많은 경우 코드의 복잡성이 증가할 수 있다.
- 구조의 확장성 제한
- 새로운 제품 군을 추가할 때마다 새로운 팩토리와 제품 클래스를 추가해야 하므로 구조적으로 확장성이 일부 제한될 수 있다.
📌 자바 속 추상 팩토리 패턴
[ DocumentBuilderFactory ]
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
public class XMLProcessor {
public static void main(String[] args) {
// 추상 팩토리 메서드를 이용한 인스턴스 생성
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 실제 구현체를 이용하여 DocumentBuilder 생성
try {
DocumentBuilder builder = factory.newDocumentBuilder();
// 이제 builder를 사용하여 XML 문서를 파싱할 수 있음
} catch (Exception e) {
e.printStackTrace();
}
}
}
📌 정리
추상 팩토리 패턴은 관련된 객체 집합을 생성하고, 이를 함께 사용할 수 있도록 인터페이스를 제공하는 디자인 패턴이다. 이 패턴은 객체들의 생성을 서로 분리하고, 클라이언트 코드가 구체적인 클래스에 의존하지 않도록 하여 시스템의 유연성을 향상한다.
다음과 같을 때 사용하면 좋다.
- 여러 종류의 관련된 객체 집합을 생성해야 하는 경우
- 생성된 객체들이 함께 사용되어야 하고, 이들의 일관성을 유지해야 하는 경우
- 새로운 객체를 추가하거나 기존 객체를 변경할 때 클라이언트 코드에 영향을 최소화해야 하는 경우
추상 팩토리 패턴을 사용하면 아래와 같은 이점을 얻을 수 있다.
- 유연성 및 확장성
- 클라이언트 코드 단순화
- 일관성 유지 및 재사용성
'OOP > Design Pattern' 카테고리의 다른 글
[Design Pattern] 구조 패턴이란? (0) | 2024.03.08 |
---|---|
[Design Pattern] 프로토타입 패턴(Prototype Pattern)이란? (0) | 2024.03.07 |
[Design Pattern] 팩토리 메서드 패턴(Factory Method Pattern)이란? (0) | 2024.03.05 |
[Design Pattern] 빌더 패턴(Builder Pattern)이란? (0) | 2024.03.04 |
[Design Pattern] 싱글턴 패턴(Singleton Pattern)이란? (2) | 2024.02.28 |