추상 팩토리 패턴이란
- 관련 객체들의 구상 클래스들을 지정하지 않고도 관련 객체들의 모음을 생성할 수 있도록 하는 패턴
- 추상 팩토리 패턴의 방식
- 각 객체군에 해당하는 개별적인 인터페이스를 명시적으로 선언한다
interface Sofa { fun hasLags() fun sitOn() } class ModernSofa:Sofa { override fun hasLags() { println("다리가 굵게 2개") } override fun sitOn() { println("여러명 앉기 가능") } } class VictorianSofa:Sofa { override fun hasLags() { println("(빅토리안)다리가 굵게 2개") } override fun sitOn() { println("(빅토리안)여러명 앉기 가능") } }
- 각 객체군에 특정 객체의 변형에 해당하는 객체군들을 찾아서 Interface로 정의를 해준다(추상 팩토리를 선언해주는 것)
- 해당 Interface는 모든 개별 객체군들의 생성 메서드를 목록화 되어있는 인터페이스로 구현해준다
interface Factory { fun createChair():Chair fun createSofa():Sofa } class ModernFactory:Factory { private val chair = ModernChair() private val sofa = ModernSofa() override fun createChair(): Chair{ return chair } override fun createSofa(): Sofa{ return sofa } } class VictorianFactory:Factory { private val chair = VictorianChair() private val sofa = VictorianSofa() override fun createChair(): Chair{ return chair } override fun createSofa(): Sofa{ return sofa } }
- 클라이언트 코드는 자신에게 해당하는 abstract Interface 를 통해서 추상 팩토리와 객체들 모두와 함께 동작해야 한다
- 클라이언트 코드에 넘기는 팩토리의 종류와 객체 변형들을 클라이언트 코드를 손상하지 않으며 자유자재로 변경할 수 있다
- 추상 팩토리 패턴의 구조
- 추상 객체들은 객체 집합을 구성하는 개별 연관 객체들의 집합에 대한 인터페이스들을 선언한다.
- 구상 객체들은 변형들로 그룹화된 추상 객체들의 다양한 구현이다.
- 각 추상 객체는 주어진 모든 변형에 대응하여 구현되어야 합니다.
- 추상 팩토리 인터페이스는 각각의 추상 객체들을 생성하기 위한 여러 메서드들의 집합을 선언
- 구상 객체들은 추상 팩토리의 생성 메서드들을 구현
- 각 구상 객체는 객체들의 특정 변형들에 해당하며 해당 특정 변형들만 생성
- 구상 객체들은 구상 객체들을 인스턴스화하나, 그 객체들의 생성 메서드들의 시그니처들은 그에 해당하는 추상 객체들을 반환해야 한다.
- 그래야 팩토리를 사용하는 클라이언트 코드가 팩토리에서 받은 제품의 특정 변형과 결합되지 않는다
- 클라이언트는 추상 인터페이스를 통해 팩토리/객체 변형의 객체들과 소통하는 한 그 어떤 구상 팩토리/객체 변형과 작업할 수 있다.
- 추상 팩토리 패턴의 적용
- 코드 내에 객체군에 다양한 집합들과 작동해야 하지만 해당 객체들이 구상 클래스들에 의존하고 싶지 않을 때
- 향후 확장성을 허용하기를 원할 수 있기 때문에
- 코드에 클래스가 있고 이 클래스의 팩토리 메서들의 집합의 기본 책임이 뚜렷하지 않을 때
- 각 클래스마다 하나의 책임만을 가지는 것이 좋다
- 하나의 클래스가 여러 객체의 유형을 상대해야 하는 경우 클래스의 펙토리 메서드들을 독립 실행형 펙토리 클래스 또는 완전한 추상 팩토리 구현으로 추출할 가치가 있을 수 있다
- 코드 내에 객체군에 다양한 집합들과 작동해야 하지만 해당 객체들이 구상 클래스들에 의존하고 싶지 않을 때
- 추상 팩토리 패턴의 장단점
- 장점
- 팩토리에서 생성되는 객체들의 상호 호환을 보장할 수 있다
- 구상 제품들과 클라이언트 코드 사이의 단단한 결합을 피할 수 있다
- 딘일 책임 원칙을 효과적으로 적용 시킬 수 있다
- 개방 폐쇄 원칙을 효과적으로 지킬 수 있다
- 단점
-
- 새로운 인터페이스들과 클래스들이 많이 도입되기 때문에 코드가 필요 이상으로 복잡해질 수 있다
- 장점
- 다른 패턴과의 관계
- 복잡성이 낮고 자식 클래스들을 통해 더 많은 커스터 마이징이 가능한 펙토리 메서드로 시작해 더 유연하면서도 더 복잡한 추상 팩토리 패턴등으로 발전 시킬 수 있다
- 추상 팩토리 메서드는 객체를 즉시 반환하지만 빌더는 객체를 가져오기 전에 몇가지 추가 생성 단계를 실행 할 수 있도록 한다
- 추상 팩토리는 하위 시스템 객체들이 클라이언트 코드에서 생성되는 방식만 숨기고 싶을 때는 퍼사드 패턴 대신 사용할 수 있다
- 브릿지에 의해 정의된 어떤 추상화들이 특정 구현들과만 작동할 수 있을 때 유용하다
- 추상 팩토리 패턴이 이러한 관계를 캡슐화 하고 클라이언트 코드에서부터 복잡성을 숨길 수 있다
- 간단한 클래스 그림
'코딩에 도움이 되는 요소 > 디자인 패턴' 카테고리의 다른 글
(디자인 패턴) 무한 복제!! 프로토 타입 패턴을 알아보자!! (0) | 2024.05.24 |
---|---|
객체를 단계적으로 생산하는 패턴!! 빌더 패턴을 알아보자 (0) | 2024.05.08 |
[디자인 패턴] 가상의 생성자를 두어서 관리하자!! 팩토리 메서드 패턴 (0) | 2024.05.03 |