스터디/디자인패턴

[design-pattern][디자인패턴]추상 팩토리 패턴(Abstract Factory Pattern)이란?

zendyne 2022. 11. 28. 16:50

추상 팩토리 는 구체적인 클래스를 지정하지 않고 관련 객체의 패밀리를 생성할 수 있는 생성 디자인 패턴입니다.

문제

가구점 시뮬레이터를 만들고 있다고 상상해 보십시오. 코드는 다음을 나타내는 클래스로 구성됩니다.

  1. 관련 제품군, 예: Chair+ Sofa+ CoffeeTable.
  2. 이 가족의 여러 변종. 예를 들어 제품 Chair+ Sofa+ 는 , , CoffeeTable와 같은 변형에서 사용할 수 있습니다 .ModernVictorianArtDeco

제품군 및 변형.

동일한 패밀리의 다른 개체와 일치하도록 개별 가구 개체를 만드는 방법이 필요합니다. 고객은 일치하지 않는 가구를 받으면 상당히 화를 냅니다.

모던 스타일의 소파는 빅토리아 스타일의 의자와 어울리지 않습니다.

또한 새 제품이나 제품군을 프로그램에 추가할 때 기존 코드를 변경하고 싶지 않을 것입니다. 가구 공급업체는 카탈로그를 매우 자주 업데이트하므로 업데이트가 발생할 때마다 핵심 코드를 변경하고 싶지 않을 것입니다.

해결책

추상 공장 패턴이 제안하는 첫 번째 사항은 제품군의 각 개별 제품(예: 의자, 소파 또는 커피 테이블)에 대한 인터페이스를 명시적으로 선언하는 것입니다. 그런 다음 제품의 모든 변형이 해당 인터페이스를 따르도록 할 수 있습니다. 예를 들어 모든 의자 변형은 Chair인터페이스를 구현할 수 있습니다. CoffeeTable모든 커피 테이블 변형은 인터페이스 등을 구현할 수 있습니다 .

동일한 개체의 모든 변형은 단일 클래스 계층 구조로 이동해야 합니다.

다음 조치는 제품군의 일부인 모든 제품(예: , 및 )에 대한 작성 방법 목록이 있는 인터페이스인 추상 팩토리 를 선언하는 것 입니다. 이러한 메서드는 이전에 추출한 인터페이스( , 등)가 나타내는 추상 제품 유형  반환 해야 합니다 .createChaircreateSofacreateCoffeeTableChairSofaCoffeeTable

각 콘크리트 공장은 특정 제품 변형에 해당합니다.

이제 제품 변형은 어떻습니까? 제품군의 각 변형에 대해 AbstractFactory인터페이스를 기반으로 별도의 팩토리 클래스를 생성합니다. 공장은 특정 종류의 제품을 반환하는 클래스입니다. 예를 들어, 는  개체  ModernFurnitureFactory만들 수 있습니다 .ModernChairModernSofaModernCoffeeTable

클라이언트 코드는 각각의 추상 인터페이스를 통해 공장과 제품 모두에서 작동해야 합니다. 이를 통해 실제 클라이언트 코드를 손상시키지 않고 클라이언트 코드에 전달하는 팩토리 유형과 클라이언트 코드가 수신하는 제품 변형을 변경할 수 있습니다.

클라이언트는 작업하는 팩토리의 구체적인 클래스에 대해 신경쓰지 않아야 합니다.

고객이 공장에서 의자를 생산하기를 원한다고 가정해 보겠습니다. 클라이언트는 공장의 클래스를 알 필요가 없으며 어떤 종류의 의자를 가져오는지는 중요하지 않습니다. 모던 모델이든 빅토리안 스타일의 의자든 클라이언트는 추상 Chair인터페이스를 사용하여 모든 의자를 동일한 방식으로 처리해야 합니다. sitOn이 접근 방식을 사용하면 클라이언트가 의자에 대해 아는 유일한 것은 어떤 방식으로든 메서드를 구현한다는 것 입니다. 또한 의자의 어떤 변형이 반환되든 항상 동일한 공장 개체에서 생산된 소파 또는 커피 테이블 유형과 일치합니다.

명확히 해야 할 것이 하나 더 남아 있습니다. 클라이언트가 추상 인터페이스에만 노출되는 경우 실제 팩토리 객체를 생성하는 것은 무엇입니까? 일반적으로 응용 프로그램은 초기화 단계에서 구체적인 팩터리 개체를 만듭니다. 그 직전에 앱은 구성 또는 환경 설정에 따라 공장 유형을 선택해야 합니다.

 

적용 가능성

코드가 관련 제품의 다양한 제품군과 함께 작동해야 하지만 해당 제품의 구체적인 클래스에 의존하지 않으려는 경우 Abstract Factory를 사용합니다. 사전에 알 수 없거나 향후 확장성을 허용하려는 경우일 수 있습니다.

Abstract Factory는 제품군의 각 클래스에서 객체를 생성하기 위한 인터페이스를 제공합니다. 코드가 이 인터페이스를 통해 개체를 만드는 한 앱에서 이미 만든 제품과 일치하지 않는 잘못된 제품 변형을 만드는 것에 대해 걱정할 필요가 없습니다.

  • 기본 책임을 모호하게 만드는 일련의 팩토리 메서드 가 있는 클래스가 있는 경우 추상 팩토리 구현을 고려하십시오 .
  • 잘 설계된 프로그램에서 각 클래스는 한 가지만 담당합니다 . 클래스가 여러 제품 유형을 처리할 때 팩토리 메서드를 독립형 팩토리 클래스 또는 완전한 추상 팩토리 구현으로 추출하는 것이 좋습니다.

구현 방법

  1. 고유한 제품 유형 대 이러한 제품의 변형 매트릭스를 매핑합니다.
  2. 모든 제품 유형에 대한 추상 제품 인터페이스를 선언합니다. 그런 다음 모든 구체적인 제품 클래스가 이러한 인터페이스를 구현하도록 합니다.
  3. 모든 추상 제품에 대한 생성 메서드 집합을 사용하여 추상 팩터리 인터페이스를 선언합니다.
  4. 각 제품 변형에 대해 하나씩 구체적인 팩터리 클래스 집합을 구현합니다.
  5. 앱 어딘가에 공장 초기화 코드를 생성합니다. 애플리케이션 구성 또는 현재 환경에 따라 구체적인 팩터리 클래스 중 하나를 인스턴스화해야 합니다. 제품을 구성하는 모든 클래스에 이 팩토리 객체를 전달합니다.
  6. 코드를 스캔하고 제품 생성자에 대한 모든 직접 호출을 찾습니다. 이를 팩토리 객체에 대한 적절한 생성 메서드에 대한 호출로 바꿉니다.

장점과 단점

  • 공장에서 받는 제품이 서로 호환되는지 확인할 수 있습니다.
  • 구체적인 제품과 클라이언트 코드 간의 긴밀한 결합을 피합니다.
  •  단일 책임 원칙 . 제품 생성 코드를 한 곳에 추출하여 코드를 지원하기 쉽게 만들 수 있습니다.
  •  개방/폐쇄 원리 . 기존 클라이언트 코드를 손상시키지 않고 새로운 변형 제품을 도입할 수 있습니다.
  • 패턴과 함께 많은 새로운 인터페이스와 클래스가 도입되기 때문에 코드가 예상보다 복잡해질 수 있습니다.

다른 패턴과의 관계

  • 많은 디자인이 Factory Method (하위 클래스를 통해 덜 복잡하고 사용자 지정 가능)를 사용하여 시작하여 Abstract Factory , Prototype 또는 Builder (더 유연하지만 더 복잡함)로 발전합니다.
  • 빌더 는 복잡한 객체를 단계별로 구성하는 데 중점을 둡니다. Abstract Factory 는 관련 개체의 패밀리를 만드는 데 특화되어 있습니다. Abstract Factory 는 제품을 즉시 반환하는 반면 Builder 는 제품을 가져오기 전에 몇 가지 추가 구성 단계를 실행할 수 있습니다.
  • 추상 팩토리 클래스는 종종 팩토리 메소드 세트를 기반으로 하지만 프로토타입 을 사용 하여 이러한 클래스에서 메소드를 구성 할 수도 있습니다 .
  • Abstract Factory 는 클라이언트 코드에서 하위 시스템 개체가 생성되는 방식을 숨기려는 경우에만 Facade 의 대안으로 사용할 수 있습니다.
  • Bridge 와 함께 Abstract Factory 를 사용할 수 있습니다 . 이 페어링은 Bridge 에서 정의한 일부 추상화 가 특정 구현에서만 작동할 수 있는 경우에 유용합니다. 이 경우 Abstract Factory 는 이러한 관계를 캡슐화하고 클라이언트 코드에서 복잡성을 숨길 수 있습니다.
  • 추상 팩토리 , 빌더  프로토타입 은 모두 싱글톤 으로 구현될 수 있습니다 .