목적
추상 팩토리 패턴은 구상 클래스를 명시하지 않고도 서로 연관되거나 의존하는 객체들을 생성할 수 있도록 하는 패턴이다.
문제
여러 프로덕트군들간 공통적인 변수들을 가지고 있는 클래스들이 있다면
개별 객체들의 기존 코드들을 변경하지 않고 새로운 프로덕트를 관련된 프로덕트군에 추가하고자 한다.
해결책
- 프로덕트들의 개별 프로덕트에 대한 인터페이스를 명시한다. 그 이후 각 프로덕트들이 해당 인터페이스를 따르도록 한다.
- 모든 프로덕트에 대한 생성 메서드의 목록을 가지는 인터페이스를 선언한다.
구조
- 추상 프로덕트는 개별 프로덕트를 위한 인터페이스를 선언한다.
- 추상 팩토리 인터페이스는 각 추상 프로덕트를 생성하는 메서드의 집합을 선언한다.
- 구상 프로덕트는 변수들로 그룹화되는 추상 프로덕트를 다양하게 구현한다.
- 구상 팩토리는 추상 팩토리의 생성 메서드를 구현한다.
각 구상 팩토리는 프로덕트의 특정 변수에 해당하고, 해당 프로덕트 변수만을 생성한다. - 구상 팩토리가 구상 프로덕트를 인스턴트화함에도 생성 메소드의 특징들은 반드시 해당 추상 프로덕트를 반환해야만 한다.
이렇게 해야 팩토리를 사용하는 클라이언트 코드가 팩토리로부터 가져온 프로덕트의 특정 변수와 결합되지 않는다.
클라이언트는 추상 인터페이스를 통해 객체와 통신하는 한 모든 구상 팩토리 / 구상 프로덕트 변수와 작업한다.
장점
- 팩토리에서 생성한 프로덕트끼리 호환되는지 확인할 수 있다.
- 구체적인 프로덕트와 클라이언트 코드 간의 긴밀한 결합을 피할 수 있다.
- 긴밀하게 결합하면 높은 의존성을 가지게 되며, 하나의 객체를 변경하게 되면 다른 객체에도 변경을 요구하게 된다. - 단일 책임 원칙. 제품 생성 코드를 한 곳에 추출할 수 있으므로 코드를 더 쉽게 지원할 수 있다.
- 개방/폐쇄 원칙. 기존 클라이언트 코드를 손상시키지 않고 새로운 제품 변형을 도입할 수 있다.
단점
- 많은 새로운 인터페이스와 클래스가 패턴과 함께 도입되기 때문에 코드는 필요 이상으로 복잡해질 수 있다.
다른 패턴과의 관계
- 많은 설계는 Factory 패턴(하위 클래스를 통해 덜 복잡하고 사용자 지정 가능)을 사용하여 Abstract Factory, Prototype 또는 Builder(더 유연하지만 더 복잡함)로 발전한다.
- Builder는 복잡한 객체를 단계별로 구성하는 데 중점을 둔다.
Abstract Factory는 관련 객체의 패밀리를 만드는 것을 전문으로 한다.
Abstract Factory는 제품을 즉시 반환하는 반면 Builder에서는 제품을 가져오기 전에 몇 가지 추가 구성 단계를 실행할 수 있다. - Abstract Factory 클래스는 Factory Methods 집합을 기반으로 하는 경우가 많지만 프로토타입을 사용하여 이러한 클래스에 메서드를 구성할 수도 있다.
- Abstract Factory는 하위 시스템 객체가 클라이언트 코드에서 생성되는 방식만 숨기려는 경우 Facade의 대안으로 사용할 수 있다.
- Abstract Factory는 Bridge와 함께 사용할 수 있다.
이 쌍은 Bridge에 의해 정의된 일부 추상화가 특정 구현에서만 작동할 수 있을 때 유용하다.
이 경우 Abstract Factory는 이러한 관계를 캡슐화하고 클라이언트 코드에서 복잡성을 숨길 수 있다. - Abstract Factory, Builder 및 Prototype은 모두 Singleton으로 구현될 수 있다.
까지가
에 발췌된 추상팩토리의 내용입니다.
근데 고에서는 클래스라는 타입 자체가 없음. 고로 고는 안써도됨. (수고ㅂㅇ)
(이)라고 말하고 싶지만 개인적으로 추상팩토리 패턴은 덕타이핑을 지원하는 고에서 완벽한 패턴이라고 생각한다.
위에있는 구조 달락에 대한 내용을 그대로 하나하나 구현해보도록 하겠다.
나는 카페를 좋아해서 카페로 예를 들면서 설명하겠다 ( 사실 커피를 좋아함 )
1.추상 프로덕트는 개별 프로덕트를 위한 인터페이스를 선언한다.
itemFactory 인터페이스가 추상 프로덕트라고 생각하면 된다.
2.추상 팩토리 인터페이스는 각 추상 프로덕트를 생성하는 메서드의 집합을 선언한다.
위의 1번 추상 인터페이스에 makeCoffee() 와 makeCake() 메서드 집합을 추가해줬다.
3.구상 프로덕트는 변수들로 그룹화되는 추상 프로덕트를 다양하게 구현한다.
메가커피 구조체와 컴포즈 구조체를 선언해줬다.
4.구상 팩토리는 추상 팩토리의 생성 메서드를 구현한다.
덕타이핑의 장점으로 구상팩토리(구조체)의 메서드를 구현함으로써 쉽게 구현할수 있다.
5.구상 팩토리가 구상 프로덕트를 인스턴트화함에도 생성 메소드의 특징들은 반드시 해당 추상 프로덕트를 반환해야만 한다.
이렇게 해야 팩토리를 사용하는 클라이언트 코드가 팩토리로부터 가져온 프로덕트의 특정 변수와 결합되지 않는다.
클라이언트는 추상 인터페이스를 통해 객체와 통신하는 한 모든 구상 팩토리 / 구상 프로덕트 변수와 작업한다.
구상 팩토리가 프로덕트를 인스턴스화 하면서 추상 프로덕트를 반환하고 있다.
여기서 이해가 어려울수 있는데 megaCoffee 는 구조체고 itemFacotry 는 인터페이스인데 어떻게 구조체를 리턴하는데
인터페이스를 반환값으로 받을수 있나? 라고 생각할 수 있다.
위의 4번으로 인해 메가커피와 컴포즈 구조체는 인터페이스가 담고있는 메서드를 구현하고 있기에 가능하다.
이제 추상팩토리 패턴을 만들었으니 이를 기반으로 원하는 커피샵을 차리고 커피와 케이크를 만들수 있다.
위의 코드는 추상팩토리 장점인
단일 책임 원칙 (제품 생성 코드를 한 곳에 추출할 수 있으므로 코드를 더 쉽게 지원할 수 있다.) 을 만족한다.
메가 커피와 컴포즈 커피만 만들었지만 우리는 위의 코드를 활용해 새로운 스타벅스 커피를 만들수 있다.
장점이자 단점인 개방/폐쇄원칙은 기존 코드를 손상시키지 않지만
새로운 제품이 있을때 구조체와 메서드를 다 구현해줘야 해서 코드가 길어 질 수 있다.
'Go' 카테고리의 다른 글
golang 빌더패턴(Builder Pattern) (0) | 2022.07.22 |
---|---|
golang 상속 (상속아님) (0) | 2022.07.21 |
golang 싱글톤 패턴(Singleton Pattern with golang) (0) | 2022.07.14 |
고에서 에러 제어 (0) | 2022.06.08 |
golang 구글 Oauth 인증 구현 (0) | 2022.05.17 |